Вопрос: Windows 8.1 DirectDraw и совместимость со старыми играми


Я пытаюсь запустить старую игру (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, чтобы эта игра обнаружила его? Я обновил последние драйверы драйверов и выполнил Runtime для конечных пользователей Microsoft DirectX 9.0c


2
2018-02-20 04:11


Источник


Нет вопросов............? - Xavierjazz
Windows 8.1 полностью совместима со старыми играми DirectX, если установлена ​​версия DirectX, которую он использует. - Ramhound
Посмотрите, что это такое, у меня установлен Runtime конечного пользователя, который должен исправлять совместимость, но это не сработало - Caleb C


Ответы:


У меня подозрительное подозрение ...

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

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

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

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

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

Sneaky user! Where is my canary!

После разборки и быстрого просмотра ссылок на строку, я нашел вызов функции, который печатает 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 с моими комментариями. Полноразмерное изображение по щелчку.

Videocard memory size detection

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

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

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

а также имеет тенденцию сообщать о том, что он чувствует:

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

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

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

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 является колоссальным 536KB и отказывается бежать.

Вы можете проверить это сами в этом онлайн 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). Я уже знаю смещение файла, но он может быть различным в вашем исполняемом файле. К счастью, hex-string 0500600900 уникальна в моем race.bin и, вероятно, в вашем. Так что получите hex-редактор (я рекомендую HxD: он бесплатный, портативный и простой в использовании) и откройте bin файл.

Сделайте поиск по шестистрочной строке:

hex-string search

После того, как найдена шестнадцатеричная строка

hex-string found

Замените его 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: vid: 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. Это один из тех допущения Я уже говорил.

6
2018-02-22 23:06



Ничего себе, огромный ответ! - TheKB