2

Я пытаюсь запустить старую игру (Nascar Heat 2002) на своем ноутбуке с Windows 8.1. Проблема, с которой я сталкиваюсь, заключается в том, что игра вылетает перед запуском, и в журналах сообщается, что видео-диск недоступен. Это файл журнала:

41.37.114: data directory: C:\Program Files (x86)\Hasbro Interactive\NASCAR Heat\Data\
41.37.115: Config Dir: C:\Program Files (x86)\Hasbro Interactive\NASCAR Heat\
41.37.274: ddraw: created directdraw with aticfx32.dll (AMD Radeon HD 8650G + HD 8600/8700M Dual Graphics)
41.37.274: ddraw: version 0.0.0.0
41.40.904: vid: 0 meg card (reported:0.523438)
41.40.904: vid: using AGP textures (1397), total: 0
41.40.905: unsupported: 0 megs of vram"

Насколько я могу судить, версия DirectDraw с Windows 8.1 не совместима со старыми играми, такими как эта. Я пробовал использовать библиотеки WineD3D, среди других оболочек / хаков ddraw, но безрезультатно. Итак, мой вопрос заключается в следующем: есть ли способ заставить эмулируемое количество vram (на моей карте есть видеопамять) либо в Windows, либо в оболочке ddraw, чтобы эта игра обнаруживала его? Я обновил драйверы катализатора до последних версий и имею среду выполнения Microsoft DirectX 9.0c для конечных пользователей

1 ответ1

6

У меня есть скрытое подозрение ...

Я чувствую запах рутинной процедуры обнаружения видеокарт. Это не имеет ничего общего с Windows и \ или DirectDraw (ну, частично, но не так, как вы думаете). Это просто старая игра, делающая предположения, которые больше не действительны. Это не редкость. Например, игра Oni вылетает на современных видеокартах:

Эта проблема была связана с переполнением определенного текстового буфера - тот, который перечисляет расширения OpenGL в файле startup.txt . Когда был написан Oni, дамп списка расширений OpenGL был намного короче, и разработчики не допускали большего дампа. Современные видеокарты почти всегда вызывают это переполнение.

Нам нужно идти глубже

У меня нет Nascar Heat 2002, но я скачал демо- версию NASCAR Heat, и у него точно такая же проблема. Так что я откинул свой отладчик и дизассемблер и провел вечер, пытаясь выяснить, что не так с игрой.

На самом деле игра состоит из двух исполняемых файлов, взаимодействующих друг с другом через семафор: основной исполняемый файл (в моем случае NASCAR Heat Demo.exe) и действительный движок игры (.\run\race.bin). Процедура обнаружения видеокарты находится в race.bin . При запуске игры основной исполняемый файл копирует race.bin в папку Windows TEMP как heat.bin и запускает его оттуда. Если вы попытаетесь переименовать race.bin в race.exe и запустить его, он ищет семафор, который должен быть создан основным исполняемым файлом, и, если он не найден, выдает следующее сообщение:

Подлый пользователь!Где моя канарейка!

После разборки и быстрого просмотра ссылок на строки я обнаружил вызов функции, который выводит сообщение vid: 0 meg card (reported:0.523438) . На самом деле это часть процедуры определения размера памяти видеокарты, которая в псевдокоде выглядит следующим образом (упрощенно):

RawVidMemSize = GetVidMemSizeFromDirectDraw()

// Add 614400 bytes (600Kb - 640x480 mode?) to vidmem size (what for?!)
RawVidMemSize = RawVidMemSize + 614400

if (RawVidMemSize < 2000000)
{
    MemSize = 0
}
else
{
    if (RawVidMemSize < 4000000)
        {
            MemSize = 2
        }

    if (RawVidMemSize < 8000000)
        {
            MemSize = 4
        }

    if (RawVidMemSize < 12000000)
        {
            MemSize = 8
        }

    if (RawVidMemSize < 16000000)
        {
            MemSize = 12
        }

    if (RawVidMemSize < 32000000)
        {
            MemSize = 16
        }

    if (RawVidMemSize < 64000000)
        {
            MemSize = 32
        }

    if (RawVidMemSize > 64000000)
        {
            MemSize = 64
        }
}

Для тех, кто интересуется, вот фактический поток управления функцией из IDA с моими комментариями. Полноразмерное изображение по клику.

Обнаружение объема памяти видеокарты

Теперь пришло время посмотреть, что происходит внутри этой процедуры. Я использовал классический прием break & enter (пропатчил первую инструкцию в race.bin входа race.bin с помощью int3), запустил NASCAR Heat Demo.exe и ждал появления отладчика. И вот, когда все стало ясно.

Размер видеопамяти, возвращаемый GetVidMemSizeFromDirectDraw() равен 0xFFFF0000 (4294901760 bytes = 4095MB 4095 МБ ), и это не имеет ничего общего с реальным (должно быть 1 ГБ на моем ПК). Оказывается, что DirectDraw не очень подходит для современной архитектуры видеокарт \ ПК

С ростом физической памяти, как RAM, так и VRAM, у этого API также возникают проблемы с копированием, поскольку он возвращает 32-битные значения DWORD размера в байтах.

и имеет тенденцию сообщать обо всем, на что это похоже:

У вас есть система с 1 ГБ или больше видеопамяти и 4 ГБ или больше системной памяти (ОЗУ).

Вы запускаете инструмент диагностики Direct-X, и он сообщает, что у вас есть неожиданно низкий объем приблизительной общей памяти на вкладке дисплея.

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

API, который DXDiag использует для аппроксимации системной памяти, не был разработан для обработки систем в этой конфигурации

В системе с 1 ГБ видеопамяти следующие значения возвращаются с соответствующей системной памятью:

╔═══════════════╦═══════════════════════════════════╗
║ System Memory ║ Reported Approximate Total Memory ║
╠═══════════════╬═══════════════════════════════════╣
║ 4GB           ║ 3496MB                            ║
║ 6GB           ║ 454MB                             ║
║ 8GB           ║ 1259MB                            ║
╚═══════════════╩═══════════════════════════════════╝

Так что в моем случае он просто сообщает значение, которое почти соответствует 32-разрядному целому числу. И вот тут дела идут плохо. Помните эту строчку?

RawVidMemSize = RawVidMemSize + 614400

Становится так:

RawVidMemSize = 4294901760 + 614400 (= 4295516160)

И 4295516160 - это 548865 более 32-битное значение может обработать (0xFFFFFFFF = 4294967295). Следовательно, целочисленное переполнение и конечный результат 548864 . Так что теперь игра думает, что мой размер vidmem составляет колоссальные 536 КБ и отказывается запускаться.

Вы можете проверить это самостоятельно в этом онлайн-эмуляторе сборки x86. Введите код ниже, в правом левом углу нажмите Windows и установите флажок « Registers . Нажмите кнопку Step и посмотрите, как 0xFFFF0000 в регистре EAX становится 0x00086000 с флагом Carry . Если вы нажмете на значение регистра, он будет переключаться между шестнадцатеричным и десятичным представлением числа.

mov    eax, 0xFFFF0000
add    eax, 0x96000

Как мне это исправить?

DirectDraw вероятно , никогда не возвращать значение более чем 32-разрядное целое число может обрабатывать 1 (это , кажется, ограничен , чтобы соответствовать независимо от фактического объема памяти. Таким образом, самый простой способ решить эту проблему - удалить RawVidMemSize = RawVidMemSize + 614400 из кода, чтобы она не вызывала переполнение. В исполняемом файле это выглядит так:

  • Мнемоника сборки: add eax, 96000h
  • Фактические коды операций (шестнадцатеричные): 0500600900

Чтобы удалить его, нам нужно заменить его инструкциями NOP (hex: 90). Я уже знаю смещение файла, но оно может отличаться в вашем исполняемом файле. К счастью, шестнадцатеричная строка 0500600900 уникальна в моем race.bin и, вероятно, в вашем . Так что возьмите hex-редактор (я рекомендую HxD: он бесплатный, портативный и простой в использовании) и откройте файл bin .

Выполните поиск в шестнадцатеричной строке:

шестнадцатеричный поиск

Как только шестнадцатеричная строка найдена

найдена шестнадцатеричная строка

Заменить его на 90

Patch!

Сохраните файл. HxD автоматически создаст резервную копию файла, которую вы сможете восстановить, если что-то пойдет не так.

В моем случае этого было достаточно, и я смог начать игру. Вот как heat.log выглядит после патча:

21.33.564: ddraw: создан directdraw с помощью aticfx32.dll (AMD Radeon HD 5800 Series)
21.33.564: ddraw: версия 0.0.0.0
21.34.296: видео: 64 Мб (сообщено: 4095.937500)
21.34.296: vid: использование текстур AGP (3231), всего: 64
21.34.305: vid: тройной буфер включен

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

Также было подтверждено, что такая же ошибка существует в Viper Racing. Viper Racing использует немного другое (старше?) версия игрового движка, чем Nascar, но ошибка та же: он тоже пытается добавить 614400 байт к объему видеопамяти. Значения для поиска отличаются, потому что в этом случае компилятор решил не использовать регистры и просто получил доступ к переменной из стека, то есть:

  • Мнемоника сборки: add [esp+18h+var_14], 96000h
  • Фактические коды операций (шестнадцатеричные): 8144240400600900

Приятного вождения!

  1. Это одно из тех предположений, о которых я говорил.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .