Need for Speed Underground 2 на телефоне. Не эмулятор. Сейчас объясню


Зима 2005-го. Диск куплен на рынке за 150 рублей, на обложке написано «Полностью на русском», внутри, разумеется, английский. Компьютер с GeForce FX 5200 гудит, как взлетающий Ту-154. Запускаешь игру, и из колонок Genius звучит Riders on the Storm в исполнении Snoop Dogg и The Doors. На экране мокрый асфальт Бэйвью, неон под днищем, а Рейчел пишет, что у неё есть для тебя работа.
Ради этой игры прогуливали пары, копили на апгрейд и спорили, что круче: Skyline или 350Z. Кто-то клеил на свой Hummer H2 виниловую наклейку с драконом на весь кузов. Не осуждаем, сами такие были.
Прошло двадцать лет. Underground 2 по-прежнему прекрасна, только на современной Windows без плясок с бубном не запускается, а уж на телефоне и подавно. Нормальные люди в такой ситуации ставят эмулятор и смиряются с тормозами. Авторы проекта nfsu2-recompiled пошли другим путём, и от их пути становится немного неловко.
Сразу дисклеймер: проект не мой. Я перевёл README на русский и поправил пару мелочей, так что хвалить чужую работу могу без ложной скромности.
Нет, это не эмулятор
Эмулятор делает вид, что он процессор Pentium 4. Он читает x86-инструкции прямо во время игры и на лету переводит их в команды ARM. Работает, но телефону тяжело: он одновременно изображает компьютер из 2005-го и пытается что-то нарисовать.
Здесь сделали наоборот. Взяли оригинальный SPEED2.EXE и заранее, один раз, перевели его целиком в код на C. Функция за функцией, инструкция за инструкцией. Потом этот C собрали обычным компилятором под Android. В итоге на телефоне работает нативная программа, и в ней нет ни одной x86-инструкции. Это называется статической рекомпиляцией. С консольными играми такой трюк уже проделывали, а для PC-игр это всё ещё редкость.
Исходников игры у авторов нет. EA их не публиковала, утечек не было. Есть только exe-файл на 4,8 МБ.
Из exe в 9 миллионов строк
Вскрытие показало много интересного. Внутри exe записана дата сборки 9 февраля 2005 года, а в заголовке стоит 15 сентября 1987-го. Нет, игру не собирали при Горбачёве. Просто когда-то с exe сняли защиту SecuROM, сдампив его из памяти, и заголовок при этом немного пострадал.
Ещё в импортах нашлись функции для игры по модему. Модемный мультиплеер на телефон переносить, к счастью, не стали.
Цифры после перевода в C выглядят так:
27 742 функции, найдено около 99,9 % всего кода игры;
8,9 миллиона строк C, 454 мегабайта текста;
самый большой файл весит 1,6 миллиона строк, и компилятор сидит над ним три с половиной минуты;
готовый exe для Windows весит 115 МБ, хотя оригинал занимал 4,8. Прогресс.
Код получается очень дотошным: у каждой строки есть комментарий с адресом и исходной ассемблерной инструкцией. Читать его можно, но лучше не перед сном.
Как обмануть игру 2005 года
Часть кода игры написана под 3DNow! — набор инструкций AMD, который вымер примерно тогда же, когда вышла Underground 2. Таких мест почти три тысячи. Поддерживать 3DNow! никто не стал. Игре просто соврали: виртуальный процессор говорит, что такого не умеет, и игра послушно выбирает обычную ветку кода. Три тысячи проблем исчезли без единой строчки кода.
Ещё в игре есть проверка «а не процессор ли у нас Cyrix». Отвечать на неё честно оказалось сложно, поэтому функцию заменили на заглушку, которая всегда говорит «нет, не Cyrix». В 2026 году это, мягко говоря, правда.
Пожалуйста, вставьте диск 2
В какой-то момент рекомпилированная игра показала окно Please insert Disc 2. Первая мысль: что-то сломалось. Проверили оригинальный exe, и он показал ровно то же самое. Рекомпиляция оказалась настолько точной, что требует вставить в телефон компакт-диск.
Спасли разработчики из 2004 года. В коде нашёлся отладочный переключатель: если в папке с игрой лежит пустой файл с именем foobar, проверка диска отключается. Поэтому теперь foobar честно копируется на каждый телефон вместе с игрой. Жаль, что он не попадался нам на глаза в 2005-м, когда диск с рынка переставал читаться.
Детектив про чёрные машины
Самая красивая история проекта. Игра уже запускалась, показывала меню, но машины в гараже были чёрными, как будто их кто-то перекрасил в стиле «мокрый асфальт». А при загрузке гонки игра падала.
Чтобы искать такие баги, авторы сделали хитрую штуку: умеют запускать часть функций игры в оригинальном виде, а часть в рекомпилированном. Если баг пропадает, значит, он в этой части. Дальше делим пополам и так до одной функции.
Виноватой оказалась одна проверка в духе «если номер меньше или равен нулю, пропусти». Код на C был написан правильно. А вот компилятор Microsoft при оптимизации решил, что знает лучше, и тихо выкинул проверку на отрицательные числа. Номер -1 проскакивал дальше, и игра падала.
Это не догадка: автор написал отдельный маленький тест без кода игры. Без оптимизаций — 0 ошибок. С оптимизацией — 32 768 ошибок, ровно на всех отрицательных числах. После обходного пути машины снова стали цветными. Мораль: если ваш код генерирует другой код, компилятор будет ходить по таким тропинкам, куда не забредал ни один живой программист.

Переезд на телефон
На Windows игра поехала к 7 октября 2026 года. Дальше тот же C нужно было собрать под ARM64, и тут начались новые приключения.
Память. Игра 32-битная и хранит адреса в 32 битах, а телефон 64-битный. Поэтому для игры резервируется отдельный кусок адресного пространства на 4 ГБ, и все её адреса считаются от его начала. Оперативную память это не съедает, просто игра думает, что живёт в своём 2005 году.
Windows. На Android нет Windows, а игра активно её использует: кучи, файлы, потоки, окна. Всё это пришлось написать заново. Причём если игра просит функцию, которую ещё не написали, выполнение честно останавливается и сообщает, чего не хватает. Первый запуск на телефоне дошёл до создания кучи и встал. Потом до следующей функции. Потом до следующей. Медленно, зато без загадочных падений через сорок минут гонки.
Графика. Игра рисует через Direct3D 9, а на телефоне есть только Vulkan. Между ними работает DXVK — тот же переводчик, на котором держатся Windows-игры в Steam Deck. Его адаптировали под Android. Нагрузка там приличная: в гонке игра делает до 60 тысяч вызовов Direct3D за кадр. В 2005 году видеокарта такое переваривала не моргнув, а теперь каждый вызов проходит через переводчик.
Самое смешное: шейдеры в игре лежат в виде исходников и компилируются при запуске. Получается, на вашем телефоне работает компилятор шейдеров Microsoft 2004 года, переведённый в C, а его результат DXVK переводит ещё раз, уже для Vulkan. Матрёшка, которую никто не заказывал, но она работает.
Звук. Звук в игре записан в 22 кГц, а телефону нужны 48. Сначала пересчитывали по-простому, и пользователи жаловались на шипение. Потом поставили нормальный фильтр, и Riders on the Storm снова звучит как надо.
56 % времени в очереди
Игра запускает шесть потоков: графика, звук, загрузка трассы и так далее. Работать одновременно им нельзя, поэтому они по очереди передают друг другу «процессор».
Тестировщики на флагманах жаловались на 20 FPS. Профилировщик показал, что поток графики больше половины времени просто ждёт своей очереди. Оказалось, что потоки передавали управление как горячую картошку: каждый следующий получал уже истёкшее время и тут же отдавал его обратно. Сто раз за кадр.
После исправления на старом Redmi Note 8 вместо 20 FPS стало 28, вместо 28 — 35. На Galaxy S24 Ultra игра держит 35–51 FPS. Для сравнения: на нашем FX 5200 в 2005-м было примерно столько же, только с ним было слышно, как он старается.
Широкий экран
Underground 2 рассчитана на квадратные мониторы 4:3. На вытянутом экране телефона интерфейс расползается. На PC для этого давно есть WidescreenFix от ThirteenAG, но он правит машинный код игры прямо в памяти, а машинного кода здесь больше нет. Поэтому каждую его правку переписали в виде вставок в рекомпилированный C. Заодно миникарту подняли наверх, чтобы она не пряталась под большим пальцем.

Сенсорное управление можно настроить под себя: двигать и масштабировать кнопки, рулить наклоном телефона или подключить геймпад от Xbox или PlayStation. Можно выбрать лимит в 30, 60 или 120 кадров, если телефон начинает греться сильнее, чем GeForce FX.
Что в итоге
Больше всего мне нравится в этом проекте подход. Никто не переписывал игру заново и не гадал, как она должна себя вести. Есть оригинальный exe, и любое поведение сверяется с ним. Если что-то расходится, ищут настоящую причину, а не подпирают костылём. Поэтому в итоге и нашёлся баг в компиляторе Microsoft, а не очередная заплатка «чтобы не падало».
8,9 миллиона строк, компилятор шейдеров 2004 года и пустой файл foobar — и всё это ради того, чтобы в автобусе снова заиграла Riders on the Storm, а Рейчел написала, что у неё есть для тебя работа.
Для запуска нужна своя копия игры: в проекте нет ни кода, ни ресурсов EA, весь C генерируется из вашего SPEED2.EXE. Нужен телефон на Android 10 или новее с поддержкой Vulkan.
Ссылки:
codepdbh/nfsu2-recompiled — проект и APK в релизах
sp00nznet/pcrecomp — рекомпилятор, который превращает exe в C
ThirteenAG/WidescreenFixesPack — тот самый WidescreenFix
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.