Добавление широкоформатных разрешений в Grand Theft Auto

    image
    Глядя на серию постов о тридцати строчном javascript программировании, тоже захотелось что-нибудь написать, правда не в 30 строк, но потратив минимум времени, just for fun. Был скачан установщик классической Grand Theft Auto для Windows, а т.к. эта GTA работает только в стандартных разрешениях с соотношением сторон 4:3, я решил написать плагин, который бы запускал её в родном разрешении моего монитора(1920x1080).



    Перед тем как приступить непосредственно к написанию плагина, нужно как-то загружать его в процесс игры. Для этого я использую универсальный ASI Loader. GTA 1 — игра довольно старая, а значит самым оптимальным вариантом будет использование ddraw.dll. Убедиться, что Grand Theft Auto.exe действительно использует эту библиотеку можно через хекс редактор:


    Копирую содержимое архива в папку Grand Theft Auto\WINO(папка с исполняемым файлом), переименовываю dinput8.dll(ASI Loader) в ddraw.dll. Зная, что игра запустится в низком разрешении, создаю в этой же папке пустой файл wndmode.ini. Т.к. ASI Loader включает в себя wndmode.dll, о которой на хабре уже было упоминание, при наличии файла wndmode.ini GTA должна отобразиться в окне.

    При первом запуске тестовый плагин рапортует, что все работает, и можно писать свой:
    image

    Открылось меню игры, в таком вот виде:


    А еще оказалось, что игра вылетает при сворачивании, и от оконного режима пришлось отказаться, wndmode.ini был удален. Также была удалена папка scripts, за ненадобностью. Запускаю игру снова, теперь при сворачивании/разворачивании не вылетает, и выглядит так:


    Естественно 1024х768 в 2013 году меня не устраивает, поэтому в Visual Studio создаю новый проект Win32, тип — DLL, а в свойствах выставляю:
    • Конфигурация — Release
    • Набор символов — Использовать многобайтовую кодировку
    • Библиотека времени выполнения — Многопоточная (/MT)
    • Конечное расширение — .asi
    • Выходной каталог — E:\Games\Rockstar Games\Grand Theft Auto Classics\Grand Theft Auto\WINO\


    Основа плагина:
    #include "stdafx.h"
    #include "CPatch.h"
    
    DWORD WINAPI Thread(LPVOID param)
    {
    
    
    	return 0;
    }
    
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
    {
    	if (reason == DLL_PROCESS_ATTACH)
    	{
    		HANDLE HndThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&Thread, NULL, 0, NULL);
    	}
    	return TRUE;
    }
    


    Теперь нужно узнать, какие адреса памяти хранят в себе текущее значение разрешения экрана. С их помощью можно будет найти функции, в которых производится запись этого значения и заменить эту запись на свою. Запускаю игру, нажимаю клавишу F11, она позволяет менять разрешениe экрана:


    По умолчанию было выставлено 1024х768, открываю Cheat Engine, в нем выбираю процесс Grand Theft Auto.exe, в параметрах поиска выставляю следующие настройки:


    После нажатия кнопки First Scan было найдено около двадцати тысяч адресов, чтобы отсеять лишние, я несколько раз менял разрешение в игре и искал новые значения через кнопку Next Scan. Тоже самое было сделано и для высоты, в итоге я получил около двух десятков адресов:


    Простоe изменение этих адресов не дает результата, так как они перезаписываются актуальным значением сразу после разворачивания игры.
    Совсем не в полной уверенности что это сработает, я решил, что стоит попробовать заменить команды записи оригинального разрешения на своё собственное. Дизассемблировав Grand Theft Auto.exe в IDA, первым делом начал смотреть параметры вызовов стандартных функций CreateWindowExA, SetWindowPos, ShowWindow, пока не наткнулся на это:
    image

    Перед вызовом функции CreateWindowExA игра помещает в стэк значения nWidth и nHeight, которые находятся по адресам 0x787310 и 0x787314. Эти адреса есть в таблице Cheat Engine, так что начать подмену я решил именно с них. Для этого в IDA нажимаю «X» на nWidth, смотрю где происходит запись (Type — w):
    image

    В том же месте происходит запись в nHeight:
    image

    Возвращаюсь в студию, создаю функцию patch_res() и делаю прыжок на неё по адресу 0x491E4C:
    CPatch::RedirectJump(0x491E4C, patch_res);
    ~~~
    void __declspec(naked)patch_res()
    {
    	_asm
    	{
    			mov eax, 1920
    			MOV DWORD PTR DS : [0x787310], EAX
    			MOV DWORD PTR DS : [0x787370], EAX
    			MOV EAX, DWORD PTR DS : [EBX + 1B4h]
    			INC EAX
    			TEST ECX, ECX
    			mov eax, 1080
    			MOV DWORD PTR DS : [0x787314], EAX
    			MOV DWORD PTR DS : [0x787388], EAX
    
    			mov jmpAddress, 0x491E69
    			jmp jmpAddress
    	}
    }
    


    Оригинальный asm-код был скопирован из OllyDbg, т.к. код из Cheat Engine или IDA студия интерпретирует не всегда правильно, приходится исправлять. Компилирую, запускаю игру и вижу знакомую картину:


    В самой игре тоже самое:


    Из таблицы Cheat Engine переписал часть адресов, отсеяв лишние:
    	CPatch::RedirectJump(0x491E4C, patch_res);
    
    	CPatch::RedirectJump(0x414FF7, patch_res_x1);
    	CPatch::RedirectJump(0x43B7CF, patch_res_x2);
    	CPatch::RedirectJump(0x46453B, patch_res_x3);
    	CPatch::RedirectJump(0x46452C, patch_res_x4);
    	CPatch::RedirectJump(0x486848, patch_res_x5);
    	CPatch::RedirectJump(0x486852, patch_res_x6);
    	CPatch::RedirectJump(0x48C137, patch_res_x7);
    	CPatch::RedirectJump(0x48C276, patch_res_x8);
    	CPatch::RedirectJump(0x48C159, patch_res_x9);
    	CPatch::RedirectJump(0x49168B, patch_res_x10);
    
    	CPatch::RedirectJump(0x415008, patch_res_y1);
    	CPatch::RedirectJump(0x43B7D8, patch_res_y2);
    	CPatch::RedirectJump(0x464532, patch_res_y3);
    	CPatch::RedirectJump(0x48683A, patch_res_y4);
    	CPatch::RedirectJump(0x48C13D, patch_res_y5);
    	CPatch::RedirectJump(0x48C2B0, patch_res_y6);
    	//CPatch::RedirectJump(0x, patch_res_y7);
    


    Создал соответствующие функции:
    void __declspec(naked)patch_res_x1()
    {
    	_asm
    	{
    		mov eax, res_x
    			MOV DWORD PTR DS : [0x504CC0], EAX
    			mov jmpAddress, 0x414FFC
    			jmp jmpAddress
    	}
    }
    
    void __declspec(naked)patch_res_x2()
    {
    	_asm
    	{
    		mov edx, res_x
    			MOV DWORD PTR DS : [0x5C0C00], EDX
    			mov jmpAddress, 0x43B7D5
    			jmp jmpAddress
    	}
    }
    
    ~~~~~~~
    
    void __declspec(naked)patch_res_y6()
    {
    	_asm
    	{
    		mov eax, res_y
    			MOV DWORD PTR DS : [0x787AF0], EAX
    			mov jmpAddress, 0x48C2B5
    			jmp jmpAddress
    	}
    }
    
    void __declspec(naked)patch_res_y7()
    {
    	_asm
    	{
    		mov edx, res_y
    			MOV DWORD PTR DS : [0x4B48C0], EDX
    			mov jmpAddress, 0x48AE8B
    			jmp jmpAddress
    	}
    }
    


    res_x и res_y установил в 1920 и 1080, да вот результат не очень порадовал:


    Хотя полдела сделано, игра работает в 1920х1080. Поначалу я решил, что рендер происходит некорректно из-за того, что не все значения в таблице Cheat Engine изменены на 1920 и 1080. Но все их отловить не реально, так что я попробовал убрать редиректы на некоторые мои функции. Методом научного тыка было обнаружено, что patch_res_x4, 5 и 6 вызывают подобное поведение, а без них все работает нормально, кроме меню. Отключение x7-x10 приводит в порядок и меню.

    В итоге, того результата, на который рассчитывал, я добился:
      



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

    Исходный код доступен на GitHub, готовый фикс там же. Установщик с игрой был найден на просторах интернета, т.к. официальный на Windows 8 не запускается, да и для скачивания в данный момент не доступен. Размер exe — 774 144 байта, с другими плагин может не работать.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

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

    Комментарии 20

      +7
      ничего себе минимум времени :)
        +17
        Месье…
        Пожалуй, в свете последних статей осталось только запустить её на Windows XP x32 с памятью в 8 гигов, а саму XP — в эмуляторе x86 на Javascript длиной в 30 строк.
        +1
        Судя по скриншотам, происходит кадрирование. То есть на широкоформатном экране отображается меньше игрового мира, чем на обычном.
          0
          Так и есть, понятия не имею как в данном случае исправить пропорции. А если начать поиски, то это может надолго затянуться…
          –2
          Учитывая во-вот грядущий выход нового GTA на PC, заголовок поста немного вводит в заблуждение…
          ;-)
            +2
            Откуда инфа? Рокстаровцы молчат вроде и кругом одни предположения )
              0
              Есть только обоснованное подозрение (но это только подозрение), что выпуск состоится практически сразу (через 1-2 недели) после релиза новых приставок (PS и XBOX). Но оно основано только на слухах, так что никаких гарантий… Ждем и надеемся… :-)
                +1
                А как связан релиз новых консолей с выходом GTA V на PC?
                Игра-то вышла на предыдущем поколении, а не на грядущем.
                  0
                  Консоли старого поколения не могут показать всю возможности движка (максимальную графику). ПК — может. Консоли нового поколения — тоже могут, но они не совместимы с консолями старого (у обоих производителей), а это означает, что игру можно будет переиздать для этих консолей.
                  На месте производителей приставок я бы договорился с издателем отлижить выход игры на ПК до релиза консолей, т.к. это выгодно обеим сторонам.
                  Те, кому очень не терпелось поиграть, купили игру для консолей старого поколения. Эти же люди скорее всего купят игру для консолей нового поколения или ПК, когда она выйдет.

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

                  П.С.
                  Всё сказанное выше — только размышления вслух.
          +4
          (робким голосом) А GTA2?
            +2
            (шепотом) А погуглить?

            image

            Только поле зрения будет меньше, чем в 4:3 (будет как в сабже на скриншотах) и субтитры обрезаются.
              0
              На самом деле для GTA2 уже все было сделано, просто отдельно не публиковалось, да и использовались там другие моды. Вобщем, раз интерес есть, собрал все файлы в кучу и выложил тут. Скриншот. Единственная проблема этого фикса — отсутствующие субтитры внизу экрана, но зато пропорции корректные.
              +2
              Когда читаю такие статьи, порой хочется подойти к зеркалу, посмотреть на себя, достать бутылку и нажраться, в попытках ответа на вопрос «а чего добился ты?»:)

              Браво, лично у меня не хватило бы ни знаний, ни упорства на такую, казалось бы, небольшую доработку игры.
                0
                Хм, а добиться отображения пиксель в пиксель — нельзя?
                  +1
                  Я уверен что можно, да не знаю как.
                  0
                  Спасибо за минутку ностальгии! GTA до перехода в 3D был гораздо более труъ :)

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

                  Самое читаемое