Перейти к содержимому


Фотография

Редактор скриптов GTA4


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 89

#41 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 06 August 2009 - 14:31

Декомпилировать неиспользуемый код мне кажется все же нужно - мало ли где пригодиться это может (к примеру, для анализа как заранее что-либо задумывалось в скриптах). Лучше даже это отключаемым/включаемым сделать. Главное чтобы все это снова не компилировалось


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

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

Как это вообще работает. Пока, предполагается, что это будет маленькая command-line программа, которой на вход скармливается архив, каталог или отдельный файл.

В зависимости от того, что ей скормили, производится компиляция или декомпиляция (можно указать что делать, параметром; например, для случая с каталогом, в котором лежат и исходники, и .obj).

Возможные сценарии работы:
* декомпиляция архива: на вход даем параметром архив, опционально - h4 для типов, сигнатурного аналза и т.д.), на выходе получаем пачку c4 и h4 (если хорошо попросили - то еще и a4, чтобы покопаться на уровне байткода)
* декомпиляция файла: на вход даем парметром .sco, globals.h4 и natives.h4 (возможно, еще какие-то хэдеры, чтобы сразу определить библиотечные функции). На выходе получаем .c4 (по запросу - a4)
* компиляция файла: на вход дается один или несколько .c4, архив и соответствующие h4. Скомпилированные файлы добавляются/заменяются в архиве.
* компиляция архива: на вход дается каталог с исходниками, globals.h4, natives.h4. На выходе получаем архив.

Опуская некоторые тонкости, как-то так.

Все скрипты полностью независимы друг от друга. Да, для них всех есть глобальный сегмент (общий для всех), но и только. Единственные методы взаимодействия скриптов - это запуск одного из другого (и проверка на загруженность/запущенность).

В принципе, я предполагаю поделить весь проект на маленький .exe и .dll со всей функциональностью.
В этом случае, .dll можно будет подключать к своим тулзам.

Самый интересный вопрос который уже давно интересует - можно ли при желании будет написать свой режим для мультиплеера?

Технических препятствий нет. Есть административные.
Т.е. требуется, чтобы у всех участников был одинаковый набор скриптов, плюс, неизвестно, как отнесется ко всему этому Live (особенно, если будут какие-то дополнения к протоколу; скажем, для нового AI).

А вот это уже крайне интересно. Что касается эпизодов IV было бы не плохо просто перекомпилировать скрипты: свести к минимуму все нововведения вызывающие недостающие на ПК natives, поменять имена моделей даже на первых порах. В общем все чтобы можно было провести работоспособный тест миссий и потом наслаивать добавки в скриптах по мере введения чего-то нового (конвертирования моделей например, катсцен и звуков).


Десятка два нэйтивов все равно придется добавлять (на них геймплей сильно завязан, буквально с первой миссии). Вот пути.. да, пути придется править (там полно путей вида E1:/...). Скорее, имеет смысл начинать с моделей, добавлять их в оригинальную игру, править скрипты, чтобы они использовались и смотреть. А скрипты из TLaD подключать уже на более поздних этапах.
You think your day was surreal? Try mine.

#42 VcSaJen

VcSaJen

    Активный участник

  • Пользователи
  • PipPipPip
  • 270 сообщений
  • Пол:Мужчина
  • Интересы:GTA, скриптинг в GTA.


Отправлено 19 November 2009 - 09:04

@Listener -
1) В учебниках по Си пишут, что в switch обязательно после выбора надо ставить break. А что будет в Script Builder, если я поставлю такой код:
int c, n;
c=1;
switch ©
{
  case 1: {n=1; c=2;}
  case 2: n=2;
  case 3: n=3;
}
Переменная n будет чему равна?

2) Примеры из шестого поста ещё в силе?

3) Реально ли составить список соответствия опкодов SA и функций GTA4 (полу)автоматом или ещё как-нибудь уже после релиза С4?

4) Нужно ещё генерация при компиляции map-файла, в котором есть соответствие "строка исх.кода" - "оффсет", "функция скрипта" - "оффсет". Например:
[functions]
0000183C=DoFade
00001A88=GetObject
0000192C=MyProc1

[lines]
00000184=9 
00000194=10
000001A0=11
000001B8=12
000001C4=13
000001D2=15


#43 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 20 November 2009 - 05:44

1) n == 3 switch такой же, как в C/C++ - я даже встречал в некоторых скриптах fall-through блоки. 2) все примеры пока в силе. Более того, последние три месяца мне было совсем не до компилятора. (При большой загрузке, время удается выкраивать урывками, поэтому был выбор - либо ничего не делать, либо заниматься чем-то , что можно делать кусочками. Например, форматами) 3) Полуавтоматом - нет. Руками - вполне реально. То, что используется в качестве имен нэйтивов - это внутренние рокстаровские имена, которые не менялись, как минимум, со времен GTA2 (даже не III). 4) У меня были идеи на эту тему. По большому счету, нужно выводить адреса не кода, а локальных переменных. Поскольку оптимизатора нет, перевод текст -> байткод, получается однозначный и обратимый. Сопоставить имена, взятые из исходника, конструкциям байткода - уже решенная задача. С локальными перемеными - сложнее (в принципе, эту задачу тоже можно решить без привлечения дополнительных сущностей). Как совсем предельный случай, можно сделать загрузку непосредственно исходника, с компиляцией "на лету" (там есть специальный хук на загрузку скрипта). Ладно, это была оптимистичная часть. Теперь перейдем к пессимистичной. Как уже известно, в новом патче не только был добавлен недостающий код из TLaD (плюс, как минимум, один новый нэйтив, отсутствующий не только в TLaD, но и в TBoGT), но и полностью вырезаны все имена нэйтивов. Вместо них используются хэши, посчитанные по неизвестному алгоритму. Более того, есть некоторая вероятность, что это вообще не хэши, а специально сгенерированные случайные числа. Мне удалось, за трое суток работы, восстановить соответствие (что будет использовано в новом ScriptHook и, предположительно, в Alice). (Еще сутки, я после этого отсыпался). Совместным решением, было принято, что адреса/хэши нэйтивов не будут распространяться публично. Предполагается, что это как-то сможет уменьшить количество читеров. Вопрос, что в связи с этим, делать с проектом скриптового компилятора. В случае ScriptHook/Alice все просто: есть загружающий/исполняющий модуль (.asi), который может, в какой-то мере, проконтролировать, для чего используется скрипт. В случае с компилятором для "родных" скриптов - изначально предполагалось, что скрипты будут использоваться без дополнительных .asi. Как в этом случае бороться с читерами - непонятно. Это не означает, что работа над компилятором будет остановлена, просто требуется принять какое-то решение.

Сообщение отредактировал listener: 20 November 2009 - 05:45

You think your day was surreal? Try mine.

#44 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 20 November 2009 - 15:58

Мне удалось, за трое суток работы, восстановить соответствие (что будет использовано в новом ScriptHook и, предположительно, в Alice). (Еще сутки, я после этого отсыпался).
Совместным решением, было принято, что адреса/хэши нэйтивов не будут распространяться публично.
Предполагается, что это как-то сможет уменьшить количество читеров.

Честно говоря интересно кто на этот раз первым захотел сделать описание приватными).

Вопрос, что в связи с этим, делать с проектом скриптового компилятора. В случае ScriptHook/Alice все просто: есть загружающий/исполняющий модуль (.asi), который может, в какой-то мере, проконтролировать, для чего используется скрипт.
В случае с компилятором для "родных" скриптов - изначально предполагалось, что скрипты будут использоваться без дополнительных .asi. Как в этом случае бороться с читерами - непонятно.
Это не означает, что работа над компилятором будет остановлена, просто требуется принять какое-то решение.

Как вариант - сделать запрет на компиляцию natives, связанных так или иначе с сетевой игрой. Просто чтобы компилятор их воспринимал как "недопустимый текст" или синтаксическую ошибку.
в проекте gtamodding.ru: декабрь 2008 - декабрь 2012

#45 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 20 November 2009 - 16:11

Честно говоря интересно кто на этот раз первым захотел сделать описание приватными).

это был aru

Как вариант - сделать запрет на компиляцию natives, связанных так или иначе с сетевой игрой. Просто чтобы компилятор их воспринимал как "недопустимый текст" или синтаксическую ошибку.


Это не поможет: как говорят, одна из любимых развлекух - использование car spawner (в котором нет сетевого кода) во время гонок - позади себя спавнится лодка поздоровее.

Нужно что-то делать, чтобы собственные скрипты не могли исполняться во время сетевой игры (или, хотя бы, некоторых режимов).
You think your day was surreal? Try mine.

#46 VcSaJen

VcSaJen

    Активный участник

  • Пользователи
  • PipPipPip
  • 270 сообщений
  • Пол:Мужчина
  • Интересы:GTA, скриптинг в GTA.


Отправлено 21 November 2009 - 12:24

Скрипты во время старта мультиплеера перезапускаются? Если да, то просто скрытно добавить проверку на режим мультиплеера (кажется, IsNetworkSession, но он из неиспользованных) в начало скрипта, если true, то TERMINATE_THIS_SCRIPT. Если же скрипты не перезапускаются, то добавлять проверку после нативов WAIT.

как говорят, одна из любимых развлекух - использование car spawner (в котором нет сетевого кода)

Вроде бы машина для этого должна иметь NetworkId, или она его получает автоматом?

#47 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 22 November 2009 - 10:55

То есть получается, R* заменили еще и img-архивы со скриптами? Сейчас посмотрел - декомпиляторы natives не воспринимают. Что же aru в своем SparkIV делать с этим, интересно, собирается.
в проекте gtamodding.ru: декабрь 2008 - декабрь 2012

#48 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 22 November 2009 - 12:05

ну да, архив со скриптами 15 мб весит, а патч - 100 мб)

Что же aru в своем SparkIV делать с этим

а что собирается, ведь соответствие нейтивов с "новыми хэшами" уже найдено, а дальше все по той же схеме что и была раньше

#49 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 22 November 2009 - 16:24

А обязательно ли для вызова новых natives знать их адрес или достаточно просто хеша?

Можно открыть один и тот же скрипт из старого и нового script.img чтобы составить подобную таблицу:
0x62E319C6 GET_PLAYER_ID 
0x511454A9 GET_PLAYER_CHAR
0x17920FA7 DISPLAY_RADAR
 0x52632919 DISPLAY_HUD

в проекте gtamodding.ru: декабрь 2008 - декабрь 2012

#50 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 22 November 2009 - 19:50

Скрипты во время старта мультиплеера перезапускаются? Если да, то просто скрытно добавить проверку на режим мультиплеера (кажется, IsNetworkSession, но он из неиспользованных) в начало скрипта, если true, то TERMINATE_THIS_SCRIPT. Если же скрипты не перезапускаются, то добавлять проверку после нативов WAIT.

Я думал над аналогичным механизмом. Как вариант - в начале скрипта сбрасывать флаг bScriptSafeForMP, а нэйтив, который может выставить его обратное - замапить на один из неиспользуемых. (Вариантов много)

То есть получается, R* заменили еще и img-архивы со скриптами?

В боксовой версии так делается в каждом апдейте.
Вернее, там заменяется часть скриптов, через update.img.

Можно открыть один и тот же скрипт из старого и нового script.img чтобы составить подобную таблицу:

Aru составлял свою таблицу именно так. Беда в том, что там далеко не все (примерно треть нэйтивов так найти нельзя: появилось несколько новых нэйтивов, которых не было ни в старых скриптах, ни в боксовой версии). Так же, как нельзя найти сотни две нэйтивов, только анализом кода. Комбинируя оба подхода, удалось отмапить ~97% нэйтивов.

В любом случае - составление этой таблицы - не очень сложная задача, просто очень объемная.
You think your day was surreal? Try mine.

#51 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 23 November 2009 - 15:30

Странно, все-таки выложил ведь aru исходники своей новой версии ScriptHook. И очень большой интерес представляет ScriptingNatives.h.
в проекте gtamodding.ru: декабрь 2008 - декабрь 2012

#52 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 24 November 2009 - 12:13

Если внимательно посмотреть на эти "исходники", становится понятно, что исходников там нет. Там только хэдеры с интерфейсом к ScriptHook.dll
You think your day was surreal? Try mine.

#53 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 24 November 2009 - 15:17

Вижу. Да, не неинтересно так. Теперь чтобы что-то самому сделать надо будет выводить свои соответствия native-hash, еще и адреса до кучи искать. И все из-за читеров, которые сами наверняка скоро раскопают что к чему (g4mhook, так кажется он называется). p.s. listener, код, выводимый последней версией декомпилятора OpenIV (пусть с нормальными natives) соответствует твоему текущему варианту C4? Если нет, то в чем особенности.
в проекте gtamodding.ru: декабрь 2008 - декабрь 2012

#54 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 25 November 2009 - 10:36

Ну, адреса найти - нехитрая задача (объемная, но ничего сверхсложного в этом нет) Декомпиляторы - разные совсем (у них и задачи были разные: у меня - построить AST по коду, у Good-а - вывести читабельный текст). Плюс к тому, они сильно не перекрываются: у меня есть сигнатурный анализатор (что сокращает объем выводимого кода раз в шесть), в OpenIV - есть базовый DFA (т.е. в какой-то мере, определение типов переменных).
You think your day was surreal? Try mine.

#55 VcSaJen

VcSaJen

    Активный участник

  • Пользователи
  • PipPipPip
  • 270 сообщений
  • Пол:Мужчина
  • Интересы:GTA, скриптинг в GTA.


Отправлено 25 November 2009 - 12:50

То есть получается, R* заменили еще и img-архивы со скриптами?


В боксовой версии так делается в каждом апдейте.
Вернее, там заменяется часть скриптов, через update.img.

То есть замена скриптов не приводит к невозможности загрузки сохранения? Можно ли будет самим добавлять скрипты так, чтобы не начинать новую игру?

#56 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 25 November 2009 - 13:55

А с чего бы? Есть сегмент .globals, который фиксирован. Пока порядок/типы/количество переменных в нем не меняется - ничего плохого с сэйвами происходить не должно. Локальные переменные скрипта - это внутреннее дело самого скрипта.
You think your day was surreal? Try mine.

#57 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 26 November 2009 - 12:52

Базу по пятому патчу на днях кину в dropbox.

Если будет возможность - скинь туда же несколько декомпилированных скриптов твоей текущей версией SciptBuilder. В разных вариантах (если такие имеются) - HighLeverCode, ControlFlowCode, RageASMCode.
в проекте gtamodding.ru: декабрь 2008 - декабрь 2012

#58 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 28 November 2009 - 14:04

В общем написал я собственный дизассемблер SCO скриптов (пока что достаточно простой). Алгоритм чтения полностью сделал самостоятельно, не глядя в другие какие-либо источники. Только лишь частично цветовую схему взял из SCOReasearch GooD-а (на деле же перекомпилировать эту программу не удалось так как отсутствует "SomeListUnit.pas"). В общем, работа практически с нуля сделана. Результат - дизассембелированный код получается очень даже правдоподобным, практически как в SCOResearch (есть некоторые не точности c ipush1 которые мне не понятны). Можно даже ассемблер сделать сразу же, только вот скриптить так очень сложно будет). Могу привести примеры получившегося кода в сравнении с разными версиями других теущих дизассемблеров. Теперь следующих шаг - превращение этого кода в нормальный читабельный вид высокого уровня. Я хочу сделать не С++ синтаксис, а именно Delphi/Paskal. Но вот проблема - с чего начать? Как вести анализ кода?
в проекте gtamodding.ru: декабрь 2008 - декабрь 2012

#59 listener

listener

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 356 сообщений
  • Пол:Мужчина
  • Город:Ft.Lauderdale


Отправлено 29 November 2009 - 06:17

А что непонятного с ipush1?
if (code >= 80) // ipush1
		return new COpcodePushInt (((int)code)-0x60, 1); // параметры: аргумент, длина команды

Я же давал сылку на RCT ? Вот ее и прочесть пару раз (чтобы стало понятно, как это работает и непонятные сокращения не вызывали недоумения).

Методика простая:
1) дизассемблирование
2) свертка команд и идиомный анализ (заменяем команды высокоуровневыми аналогами, чтобы анализаторам было жить проще)
3) CFA/DFA - сворачиваем код в CFG и список переменных.
4) Строим AST на базе CFG
5) Сигнатурный анализ - сворачиваем повторяющиеся и убираем стандартные функции.
6) Выводим в текст построенный список переменных и AST.

Что касается синтаксиса, у меня вывод сделан методом printCode в каждом узле AST. Текст может выводиться на любом языке. Для примера, вывод while (второй по размеру, после if):

void ANodeWhile::printCode (DWORD depth) {
	indent (depth);
	printf ("while (");
	m_pCond->print (); // выводим условие цикла
	printf (")");
	if (m_pChain && m_pChain->m_pNext) // если оператор цикла составной, открываем скобку
		printf (" {");
	printf ("\n");
	printStatement (depth, m_pChain); // выводим оператор
	if (m_pChain && m_pChain->m_pNext) { // закрываем скобку, если нужно
		indent (depth);
		printf ("}\n");
	}
}

Вывод тела функции выглядит так:
printf ("{\n");
	if (m_pBody) 
		m_pBody->printStatement (0, m_pBody);
	printf ("}\n");

Возвращаясь к паскалевскому синатксису: уже решил, что делать с fall-through блоками в switch? Вводить для них специальный оператор (противоположный break по смыслу)?
You think your day was surreal? Try mine.

#60 Dageron

Dageron

    Активный участник

  • Пользователи
  • PipPipPip
  • 1130 сообщений
  • Пол:Мужчина
  • Город:Пермь


Отправлено 29 November 2009 - 11:08

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

Далее, второй - замена команд высокоуровневыми аналогами. Вот тут-то, на этапе Control Flow Code и появляется заминка.
Построение asm sub-ов идет нормально, т.е. если в скриптовом файле четыре потока, то будет создано четыре asm sub-а (например, sub_0, sub_21, sub_81, sub_186 - это из darts_trigger.sco). Далее возникает непонятность с типичными циклами и условиями (про switch даже не говорю пока что). Как известно, все на низком уровне сделано через jmp(34), jmpf(35), jmpt(36).

Т.е. можно разобрать самое простое условие if then else

Допустим, есть некий код на низком уровне (цифры слева-адрес):
0	 enter 0 2
  4	 native n_3B0C6738 0 2
 11	 jf @40
 16	 j @35
<snip> //тут уже sub другой совсем, но это нормально
 35	call sub_21
 40	ipush 0
 41	native n_266716AC 1 0
<snip1>

В Control Flow он должен выглядеть как:
asm sub_0(...)
{
	enter 0 2
	native n_3B0C6738 0 1
	if true (...) 
	{
		call sub_21
	}
	ipush1 0
	native n_266716AC 1 0
<snip1>
}

Не могу понять алгоритм как реализовать такое. Т.е. сначала читается "jf @40" (т.е. что в false), далее это запоминается, читается все что по идее true - в нашем случае "j @35". Смещаемся на 35, читаем команды - тут только одна, "call sub_21". А далее, наша позиция в памяти совпадает с адресом 40 и поэтому условие закрывается. На логическом уровне все понятно, а вот на деле как кодогенератор сделать - заминка появляется. Да и кроме того бывает что есть "условие в условии" и т.п.
в проекте gtamodding.ru: декабрь 2008 - декабрь 2012




Количество пользователей, читающих эту тему: 2

0 пользователей, 2 гостей, 0 анонимных