#26 18-09-2009 13:05

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: GTA IV. помогите, пожалуйста, с путями

После того, как файл загружен в базу, он в ней хранится весь. Больше никаких операций с оригинальным файлом не производится.

База данных содержит данные оригинального файла, информацию о том, где в ней код, а где данные, комментарии, имена функций, структуры и многое другое.

Кнопки для компиляции кода в IDA нет (т.к. декомпиляции как таковой не производится). Есть кнопка produce exe, но для PE (стандартного виндового файла) она не работает. Более того, потребности в ней нет, т.к. в IDA редактируется не сам файл а всего лишь его визальное представление.

В принципе, покопавшись в менюшках, можно включить меню "Patch program". В нем можно менять содержимое файла, но большой практической пользы в этом нет. Если вдруг потребуется что-то масштабно поменять - сохранить файл (или его части) можно через .idc, но, еще раз, от этого больше проблем, чем пользы.

Можно обойтись и без asi, но проблем будет не в пример больше.
Мало создать новые массивы, под них нужно найти память, т.е. придется менять всю структуру файла. Я бы не рекомендовал с этим возиться.

Следующей частью примера должна быть как раз заготовка .asi. (Я сейчас на объекте, с мобильника это делать неудобно smile )

Offline

#27 19-09-2009 23:09

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: GTA IV. помогите, пожалуйста, с путями

Итак, пора отступить от теории.
У нас есть восстановленная функция, которая читает файлы путей. Заменим ее своей.
Это решит сразу две задачи: во-первых, даст полный контроль над читаемыми файлами, во-вторых, сразу даст контроль над половиной обращений к данным путей.

Что нам требуется сделать. Мы заменяем функцию CTrackManager::readTrackFiles. Она статическая и в нее не передается параметров (не то, чтобы это на что-то чильно влияло, но все будет проще).
Из нее вызывается Функция CTrackManager::readTrackFile. Она статическая (без this), __cdecl, ей передается десять параметров (имя файла и девять указателей). Имя файла мы можем передать сами, а массивы пока используем оригинальные.

Чтобы не возиться лишний раз с ассемблером, вызовем ее по указателю.

void (__cdecl *CTrackManager__readTrackFile) (char * pszFileName, TrackNode ** ppTrackNodes, DWORD * pdwTrackSize, 
	float * pfTrackLength, DWORD * pdwStationNameCount, Vector3 * ppvStationCoords, 
	float * ppfStationDistances, BYTE * pnbStationTypes, DWORD * pdwStationNameHashes, int * pnStationNodeNumbers) = 
(void (__cdecl *)(char *, TrackNode**, DWORD *, float *, DWORD *, Vector3 *, float *, BYTE *, DWORD *, int *))
(0xAC1880+dwLoadOffset);

Выглядит громоздко, но, в сущности, кроме перечисления параметров (два раза, один раз в типе функции, второй раз - в приведении типа) здесь ничего нет.

Поскольку мы пока используем оригинальные массивы, на них тоже объявим указатели.

TrackNode ** _trackNodes = (TrackNode **)(0x14D278C+dwLoadOffset);
DWORD * _trackSizes = (DWORD *)(0x14D275C+dwLoadOffset);
float * _trackLengths = (float *)(0x14D17A8+dwLoadOffset);
DWORD * _stationNameCounts = (DWORD *)(0x14D1BD8+dwLoadOffset);
Vector3 * _stationCoords = (Vector3 *)(0x14D27C0+dwLoadOffset);
float * _stationDistances = (float *)(0x14D1FD0+dwLoadOffset);
BYTE * _stationTypes = (BYTE *)(0x14D16B8+dwLoadOffset);
DWORD * _stationNameHashes = (DWORD *)(0x14D2398+dwLoadOffset);
int * _stationNodeNumbers = (int *)(0x14D1C10+dwLoadOffset);

По мере того, как оригинальные массивы будут заменяться своими (с правкой адресов в exe или заменой функций), здесь будут появляться массивы вместо указателей.

Для общего упрощения кода, вместо двенадцати вызовов CTrackManager::readTrackFile, сделаем один цикл. Это позволит, в дальнейшем, добавлять новые файлы треков в две правки (добавить новое имя и поменять общее количество).

void CTrackManager__readTrackFiles () {
	for (DWORD i = 0; i < TRACK_COUNT; i++) {
		if (trackNodes[i] == NULL)
			CTrackManager__readTrackFile (
				trackFileNames[i], 
				_trackNodes+i, 
				_trackSizes+i, 
				_trackLengths+i,
				_stationNameCounts+i, 
				_stationCoords+i*STATIONS_PER_TRACK, 
				_stationDistances+i*STATIONS_PER_TRACK,
				_stationTypes+i*STATIONS_PER_TRACK, 
				_stationNameHashes+i*STATIONS_PER_TRACK,
				_stationNodeNumbers+i*STATIONS_PER_TRACK);
		trace ("TRACK: '%s' => %d nodes, %d total length\n", trackFileNames[i], _trackSizes[i], (int)(_trackLengths[i]));
	}
}

Почти все. Осталось только подменить оригинальную функцию нашей.
В DllMain, при обработке DLL_PROCESS_ATTACH, вставляем в начало заменяемой функции, переход на свеженаписанную замену.
При использовании xliveless, все уже подготовлено, достаточно добавить строчку

injectFunction (0xAC1D40, (DWORD)CTrackManager__readTrackFiles);

При использовании другого .asi-loaderа, нужно вызывать VirtualProtect, чтобы разрешить модификацию кода и посчитать смещение (как это делается, можно посмотреть в исходниках самого xliveless).

Компилируем написанное как .dll и кладем в каталог plugins (либо, переименовываем в .asi и кладем в основной каталог игры).

После этого, в xlive_trace.log должны появиться строчки:

19/09/2009 20:01:11.897 Log started (xliveless 0.98)
19/09/2009 20:01:11.897 GetModuleHandle returns 00400000
19/09/2009 20:01:11.897 Patching OK (1.0.4)
19/09/2009 20:01:11.897 [tracks plugin]: successfully loaded
19/09/2009 20:01:11.897 plugin loader: loaded 'plugins\tracks.dll'

... здесь пропущена дальнейшая трассировка ...

19/09/2009 20:02:06.750 TRACK: 'common:/data/paths/TracksQueens.dat' => 1247 nodes, 12717 total length
19/09/2009 20:02:06.761 TRACK: 'common:/data/paths/TracksQueens2.dat' => 1272 nodes, 12725 total length
19/09/2009 20:02:06.771 TRACK: 'common:/data/paths/TracksBronx.dat' => 850 nodes, 8474 total length
19/09/2009 20:02:06.780 TRACK: 'common:/data/paths/TracksBronx2.dat' => 805 nodes, 8431 total length
19/09/2009 20:02:06.780 TRACK: 'common:/data/paths/cablecar_northern.dat' => 10 nodes, 591 total length
19/09/2009 20:02:06.781 TRACK: 'common:/data/paths/cablecar_southern.dat' => 10 nodes, 591 total length
19/09/2009 20:02:06.781 TRACK: 'common:/data/paths/TracksPlaneOnGround1.dat' => 12 nodes, 811 total length
19/09/2009 20:02:06.781 TRACK: 'common:/data/paths/TracksPlaneOnGround2.dat' => 4 nodes, 842 total length
19/09/2009 20:02:06.781 TRACK: 'common:/data/paths/TracksPlaneInFlight.dat' => 8 nodes, 14476 total length
19/09/2009 20:02:06.782 TRACK: 'common:/data/paths/TracksPlaneInFlight2.dat' => 10 nodes, 15566 total length
19/09/2009 20:02:06.782 TRACK: 'common:/data/paths/TracksPlaneInFlight3.dat' => 8 nodes, 14476 total length
19/09/2009 20:02:06.782 TRACK: 'common:/data/paths/TracksPlaneInFlight4.dat' => 10 nodes, 15566 total length

Все. Половина дела сделана. Остались обращения к массивам.

http://public.sannybuilder.com/sources/ … plugin.rar
полный исходник и скомпилированный плагин (для компиляции нужны еще xliveless.h и xlive.lib)

Offline

#28 20-09-2009 10:07

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: GTA IV. помогите, пожалуйста, с путями

оу...ну наконец-то, нормальный гайд по созданию asi))
всё не так уж сложно...


GIMS developer

Offline

#29 21-09-2009 14:00

cutik
Registered: 11-09-2009
Posts: 24

Re: GTA IV. помогите, пожалуйста, с путями

В общем, как я понял: есть две функции, readTrackFiles и readTrackFile, первая вызывает вторую, и вместе они читают пути из файлов и распихивают по массивам. А мы написали свою readTrackFiles, и из нее вызываем стандартную readTrackFile с нашими параметрами.
Я так понял, мы берем все данные из игры? то есть не читаем файл самостоятельно?
А почему в конце есть это:

if (dwGameVersion == 0x00010004) {
...
} else 
 trace ("[tracks plugin]: incorrect game version (expected 1.0.4 EN)\n");

это значит, что мод будет идти только на версии 1,0,4,0? Почему не сделать его для всех версий сразу? (может быть, в других версиях другие адреса, например не 0xAC1D40, а как-то по другому? это моя догадка).
Почему STATIONS_PER_TRACK=20, ведь в разных путях разное количество станций? или это какое-то другое число?
Что за закомментированный код ближе к концу?
И что за #pragma pack?
Ну а в общем понятно, жду инструкции по обращениям к массивам)

Offline

#30 21-09-2009 15:20

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: GTA IV. помогите, пожалуйста, с путями

в разных версиях разные адреса
20 это наверн максимум станций


GIMS developer

Offline

#31 25-09-2009 19:26

cutik
Registered: 11-09-2009
Posts: 24

Re: GTA IV. помогите, пожалуйста, с путями

А на русской версии будет работать?
Сорри что долго не писал, занят был.
Скоро там продолжение? )

Если нет, я англ. поставлю, не проблема.

Last edited by cutik (25-09-2009 19:27)

Offline

#32 26-09-2009 15:04

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: GTA IV. помогите, пожалуйста, с путями

Во всех версиях - разные адреса. Сейчас, основная версия, под которую идет разработка - 1.0.4 EN

20 - действительно, лимит станций на маршрут. Кажется, он нигде жестко не прописан, поэтому, после переноса массивов никто не мешает его поменять.

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

Offline

#33 07-12-2009 22:09

Den_spb
From: Ленинград
Registered: 23-11-2008
Posts: 941
Website

Re: GTA IV. помогите, пожалуйста, с путями

А при решении той же задачи для СА в целом должна применяться такая же технология (понятно, что адреса будут другие) или будут существенные отличия?

Offline

#34 07-12-2009 23:24

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: GTA IV. помогите, пожалуйста, с путями

Если мой склероз мне ни с кем не изменял, в SA используется практически тот же код.

(В IV полностью заменены графика и физика, сильно переделан путепрокладчик и есть легкие изменения в AI. Все остальное - практически то же).

Offline

Board footer

Powered by FluxBB