Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

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

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

Перед тем как приступить непринужденно к написанию плагина, необходимо как-то загружать его в процесс игры. Для этого я использую многофункциональный 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. Тоже самое было сделано и для высоты, в результате я получил около 2-х десятков адресов:

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

Перед вызовом функции CreateWindowExA игра помещает в стэк значения nWidth и nHeight, которые находятся по адресам 0×787310 и 0×787314. Эти адреса есть в таблице 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_x45 и 6 вызывают сходственное поведение, а без них все работает типично, помимо меню. Отключение x7-x10 приводит в порядок и меню.

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

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

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

Источник: programmingmaster.ru

Оставить комментарий
БАЗА ЗНАНИЙ
СЛУЧАЙНАЯ СТАТЬЯ
СЛУЧАЙНЫЙ БЛОГ
СЛУЧАЙНЫЙ МОД
СЛУЧАЙНЫЙ СКИН
НОВЫЕ МОДЫ
НОВЫЕ СКИНЫ
НАКОПЛЕННЫЙ ОПЫТ
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB