You are not logged in.
После того, как файл загружен в базу, он в ней хранится весь. Больше никаких операций с оригинальным файлом не производится.
База данных содержит данные оригинального файла, информацию о том, где в ней код, а где данные, комментарии, имена функций, структуры и многое другое.
Кнопки для компиляции кода в IDA нет (т.к. декомпиляции как таковой не производится). Есть кнопка produce exe, но для PE (стандартного виндового файла) она не работает. Более того, потребности в ней нет, т.к. в IDA редактируется не сам файл а всего лишь его визальное представление.
В принципе, покопавшись в менюшках, можно включить меню "Patch program". В нем можно менять содержимое файла, но большой практической пользы в этом нет. Если вдруг потребуется что-то масштабно поменять - сохранить файл (или его части) можно через .idc, но, еще раз, от этого больше проблем, чем пользы.
Можно обойтись и без asi, но проблем будет не в пример больше.
Мало создать новые массивы, под них нужно найти память, т.е. придется менять всю структуру файла. Я бы не рекомендовал с этим возиться.
Следующей частью примера должна быть как раз заготовка .asi. (Я сейчас на объекте, с мобильника это делать неудобно )
Offline
Итак, пора отступить от теории.
У нас есть восстановленная функция, которая читает файлы путей. Заменим ее своей.
Это решит сразу две задачи: во-первых, даст полный контроль над читаемыми файлами, во-вторых, сразу даст контроль над половиной обращений к данным путей.
Что нам требуется сделать. Мы заменяем функцию 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
В общем, как я понял: есть две функции, 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
А на русской версии будет работать?
Сорри что долго не писал, занят был.
Скоро там продолжение? )
Если нет, я англ. поставлю, не проблема.
Last edited by cutik (25-09-2009 19:27)
Offline
Во всех версиях - разные адреса. Сейчас, основная версия, под которую идет разработка - 1.0.4 EN
20 - действительно, лимит станций на маршрут. Кажется, он нигде жестко не прописан, поэтому, после переноса массивов никто не мешает его поменять.
Продолжение будет. Просто, у меня после ежедневных двух-трехчасовых совещаний, отключается способность писать более-менее внятный текст.
Offline
Если мой склероз мне ни с кем не изменял, в SA используется практически тот же код.
(В IV полностью заменены графика и физика, сильно переделан путепрокладчик и есть легкие изменения в AI. Все остальное - практически то же).
Offline