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


Фотография

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


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

#21 listener

listener

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

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


Отправлено 28 May 2009 - 16:13

Согласить язык для игр и язык общего назаначения это разные вещи - первый должен быть удобен, а второй предоставлять большую мощь


Здесь, скорее, речь идет о чем-то промежуточном. Я здесь ставлю цель, как можно меньше отходить от того, что уже есть в IV. Любой шаг влево-шаг вправо - это необходимость правок виртуальной машины, чего хотелось бы избежать.

Что касается "псевдообъектной" структуры (Player.Health и т.д.) - пока в планах этого нет. Подобную вещь, в принципе, можно будет добавить в дальнейшем.

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

Чтобы транслировать myCar.health = 100 в SET_CAR_HEALTH (hMyCar, 100) потребуется либо хардкодинг большинства natives в языковые конструкции (чего хочется избежать любой ценой), либо придумывать механизм описания set/get (что, на данном этапе, я считаю нецелесообразным - это будет еще большая потеря универсальности). Если будет очень большая потребность в таком подходе - можно будет сделать препроцессор типа cfront.

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


Сделать автоматический стриминг - это, конечно, приятно. Но, к сожалению, в рамках движка GTA (от III и выше) - нереализуемо. Цена автоматизации загрузки и выгрузки ресурсов - либо серьезная потеря реалтаймовости, либо многократное увеличение используемой памяти.

Что касается универсальности... rage::script - это уже универсальная вещь класса Lua. Он очень компактен (вся VM и вспомогательные классы укладываются в 50К) и универсален (кроме IV, он уже используется в MidnightClub:LA и, предположительно, будет использоваться во всех играх на базе Rage). Поскольку он идеологически очень близок к тому, что использовалось в (III/VC/SA), то его можно с небольшими усилиями прикрутить и к предыдущим играм (да, потребуется делать обертки в виде natives для всех используемых опкодов, но это работа простая, хотя и масштабная).

PS. Список всех natives для примера: http://public.sannyb..._natives_pc.txt
PPS. Что касается разработки: она идет и снизу вверх, и сверху вниз. Как только эти два сойдутся (где-то в районе AST) - дело будет сделано.
You think your day was surreal? Try mine.

#22 JNikc

JNikc

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

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

Отправлено 30 May 2009 - 21:42

Чтобы транслировать myCar.health = 100 в SET_CAR_HEALTH (hMyCar, 100) потребуется либо хардкодинг большинства natives в языковые конструкции (чего хочется избежать любой ценой)


То есть, не совсем понимаю. Я вижу строчку myCar.health = 100 которую парсер, или препроцессор (ну или макропроцессор) должн заменить на SET_CAR_HEALTH (hMyCar, 100). Это просто макрос с параметрами.

А что такое хардкодинг :-) в вашем понимании? Например, как работает ваш язык - на уровне лексики, заменяя строчки байт-кодом, на уровне синтаксиса, распознавая структуры. Будет ли препроцессор?

Сделать автоматический стриминг - это, конечно, приятно. Но, к сожалению, в рамках движка GTA (от III и выше) - нереализуемо. Цена автоматизации загрузки и выгрузки ресурсов - либо серьезная потеря реалтаймовости, либо многократное увеличение используемой памяти.


Как работает уборка мусора в любом языке (java, ruby ...): если это интерпретатор в реальном времени, то, ваша правда это трудно и замедляет язык. Но если это компилятор или транслятор в более низкоуровневый код, как у нас, то мы имеем часть препроцессора которая меняет один код другим. Например низкоуровневый код такой:

Загрузить Нечто
... разный код ...
Работать с ним
... разный код ...
Выгрузить Нечто

Теперь пусть пользователь языка пишет

Работаем с чем-то 1
... разный код ...
Работаем с чем-то 2
... разный код ...
Работаем с чем-то N

Препроцессор это видит и заменяет на

Загрузить
Работаем с чем-то 1
... разный код ...
Работаем с чем-то 2
... разный код ...
Работаем с чем-то N
Выгрузить

Опять получается что-то вроде макроса.

В общем я наверно преждевременно задумался над этим. Все таки сначало нужен сам язык.

Кстати на http://sannybuilder....opic.php?id=424 я перевел англицкую справку по SCO. (Это имело смысл? Может разместить в руской вики по гта?) Там всего 78 опкодов и почти все работают со стеком, ассамблер какой-то. Ещё упомянуты таинственные натив функции, это как в Windows? Выходит все действия с игроком/игровым миром теперь не в опкодах а в функциях.

#23 listener

listener

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

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


Отправлено 31 May 2009 - 01:51

Выходит все действия с игроком/игровым миром теперь не в опкодах а в функциях.

Именно так. По всей видимости, народ в R* достал switch на две с половиной тысячи case.
Вместо этого, можно зарегистрировать любую функцию, как native (написав к ней нехитрую обертку, распаковывающую структуру с параметрами, причем я не исключаю вероятности, что она генерируется компилятором автоматически).

Подробнее про виртуальную машину было в четвертом посте этой темы.

или препроцессор (ну или макропроцессор) должн заменить на SET_CAR_HEALTH

В том-то и весь фокус. Во-первых, native - ~2500 штук. Во-вторых, они не имеют какой-то единой структуры вызова (т.е., автоматически назначить им self/this не получится). В-третьих, если это все описывать - получится еще прорва кода.

Сделать псевдообъектные обертки, конечно, можно. Но в первых приоритетах это не стоит.

Например, как работает ваш язык - на уровне лексики, заменяя строчки байт-кодом, на уровне синтаксиса, распознавая структуры. Будет ли препроцессор?

Структуры. Все как у больших (лексика, синтаксис, семантика, AST, код), только оптимизатора нет.

Препроцессор... Я пока не вижу в нем надобности. include - обязателен, насчет остального - вряд ли.

если это интерпретатор в реальном времени, то, ваша правда это трудно и замедляет язык

Реалтаймовых сборщиков мусора не бывает. Смысл принудительной загрузки моделей (и проверки, загружены ли они) состоит в том, чтобы гарантировать, что в определенной точке скрипта модель будет присутствовать в памяти.
Если так не делать, а грузить модели по первому требованию, в момент, когда модель потребуется, будет ощутимый лаг (Этим, например, иногда страдает первый Saint's Row - очень неприятно, когда игра внезапно замирает на полсекунды).

Вообще, говоря глобально, в GTA скрипт контролирует очень мало. Практически все поведение объектов и сущностей (анимация, стриминг, физика, AI, ...), сделано на жесткой логике. Часть этого можно перехватывать, но очень и очень малую часть.
Пед одновремено может выполнять до шестнадцати действий (в SA - 11). Из них скриптом можно назначить только пять, при этом их выполнение за исключением редких, заранее предусмотренных случаев, проконтролировать нельзя.

Даже совсем без скриптов, город будет жить своей жизнью.

? Может разместить в руской вики по гта?

Да, там ей и место.
You think your day was surreal? Try mine.

#24 JNikc

JNikc

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

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

Отправлено 31 May 2009 - 07:14

Даже совсем без скриптов, город будет жить своей жизнью.


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

Структуры. Все как у больших


Я опять навязываюсь, но интересно. Вот вы пишите на С и заводите структуы в которых храните... Так, например:

struct Var {	// Переменная имеет имя и значение
   string Name;
   string Value;
}

struct Fun {	// Функция имеет имя массив локальных переменных
   string Name;   
   Var[MAX_NUM] Vars;
   // тут данные для реализации функции
}

struct Clas {	// Класс с именем и с массивом функций
   string Name;   
   Fun[MAX_NUM] Funs;
}

Или это другие структуры?

Сообщение отредактировал JNikc: 31 May 2009 - 07:17


#25 JNikc

JNikc

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

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

Отправлено 02 June 2009 - 08:34

О том и речь, чтобы упростить, теперь мы можем писать 1@ = 5874, или даже $time_out = 5874, прямо при написании скрипта. В будущем бы хотелось писать просто произвольноый токен Abracadabara и присваивать ему произвольное значение. Если это делается внутри потока/функции - это локальная переменная потока/функции, если вовне - глобальная.

#26 listener

listener

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

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


Отправлено 02 June 2009 - 09:59

Временами, у меня возникают сомнения: "а нафига я это пишу? все равно практически никто не читает." В этой теме есть посты #4 и #6. Настоятельно рекомендую прочитать хотя бы их...
You think your day was surreal? Try mine.

#27 JNikc

JNikc

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

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

Отправлено 02 June 2009 - 12:30

извиняйте тогда... Я понял, что вы о структурах в скриптовом-языке... Просто интересовался, как это реализвано...

#28 listener

listener

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

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


Отправлено 02 June 2009 - 12:44

Как реализовано - пока рассказывать рано. Когда все будет дописано до какого-то рабочего состояния - будут выложены исходники. Проблема в том, что по мере копания в коде, очень много приходится переписывать. Потом рефакторить, чтобы выкинуть "провисшие" куски. Сейчас у меня уже третья итерация и, есть надежда, что она, если не последняя, то, по крайней мере, предпоследняя. С предыдущей версии, объем кода сократился почти вдвое. Изначально, предполагалось реализовать нормальный C. Потом начали постепенно выбрасываться куски, которые не ложатся на архитектуру VM. (Например, работы с адресами сейчас уже нет вообще, как явления и не будет). Ушел за ненадобностью typedef. Вместо того, чтобы описывать для каждой переменной (или хотя бы, для всех статических) storage class, гораздо проще вынести все глобальные декларации в отдельный файл. Сейчас, только в уже отрефакторенной части кода (дизассемблер, кодогенератор, AST), порядка ста классов. Рассказывать о них подробно, в свете того, что все может поменяться из-за того, что всплыла неучтенная ранее конструкция - несколько непродуктивно.
You think your day was surreal? Try mine.

#29 JNikc

JNikc

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

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

Отправлено 02 June 2009 - 13:00

будут выложены исходники.


А вот это просто здорово! Собственно все вопросы отпадают.

Например, работы с адресами сейчас уже нет вообще, как явления и не будет


Интересно будет взглянуть... Я недавно пытался разобраться в m4... Непотянул... сплошные условные компиляции, адреса, функции вложены по пять раз в друг друга...

#30 JNikc

JNikc

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

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

Отправлено 21 June 2009 - 19:20

Ещё у меня возникла пара вопросов. Скорее просто из интереса. Как вы узнаете как работает виртуальная машина SCO файлов? Есть какая-то документация, или всё через дизассемблер? Например есть опкод который складывает два целых сверху стека, и куда он помещает результат, снова на стек? Вообще какие байты нужно писать в sco файл: как узнать первый байт опкода, хэш нативной функции и т.д. Или в каком порядке нативные или скриптовые функции берут аргументы из стека? Тут ведь может возникнуть неоднозначности - один байт ни так запишешь и всё будет неправильно работать. (Удавалось ли уже записать "правильный" sco файл, чтоб работал?)

#31 listener

listener

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

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


Отправлено 22 June 2009 - 12:58

Все, что есть по виртуальной машине - получено из дизассемблера (причем из '360-й версии. Для меня PPC-шный ассемблер понятнее). В ассемблере все операции четко видны и достаточно понятны (все опкоды кроме трех-четырех были разобраны за неделю. Потом было несколько уточнений, но общая концепция не менялась). Последние непонятные моменты прояснились неделю назад. Если на первых этапах, дизассемблер скрипта выдавал порядка 5М строк (~110 мегабайт), то, после окончательной свертки конструкций и сигнатурного анализа, получилось ~600К строк (~30 мегабайт). Особая прелесть в том, что все преобразования взаимно однозначны. С записью .sco я еще не экспериментиировал. Учитывая, что ридер .sco чуть менее, чем полностью, основан на "родном" ридере из игры, никаких неожиданностей быть не должно. Эксперименты с записью начнутся после того, как будет готов парсер, хотя бы в каком-то приближении. Сейчас, я конечно могу прокрутить преобразование код-AST в обратную сторону, но особого смысла в этом нет.
You think your day was surreal? Try mine.

#32 JNikc

JNikc

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

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

Отправлено 22 June 2009 - 16:36

Хорошо,, если предложение предлагать предложения (:-0) о синтаксисе ещё в силе, то можно ли сделать некоторые упрощения как в скриптовых языках (у нас тоже скриптовый язык, но я имею в виду Python например)? Вот так например:

1. Опускать объявление типа, когда ясно, какй тип определяется:

с = '3' // Вместо char c = '3'
i = 77 // int i = 77, ведь все типы либо 16 бит, либо 32. По начальному значеню определяется тип.
h = $FFFFFFFF
f = 0.34
str = "AKA7"

2. Опускать точку с запятой, если на строке один оператор (вместо ; - \n)

3. Ну и совсем "синтаксический сахар" - множественной присваивание и определение блоков отступами:

a, b, c = 0, 1, 2
while b < 10
   c++
   a, b = b, a+b
   fun(a, b, c)


#33 listener

listener

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

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


Отправлено 22 June 2009 - 17:10

1. Я сам люблю python (см. фотку в профиле :-) ), но здесь немного не та ситуация. Python - нетипизированный язык. скрипты в IV - жестко типизированы, при том на уровне виртуальной машины. Типа char просто нет. i = 77 - неодназначная ситуация (int или float). str = "AK47" - неоднозначная ситуация (строка, как массив байтов или строка, как указатель). Когда же дело дойдет до структур - там начинается полный кошмар. У меня еще есть подзадачка data flow analysis для декомпилятора. С простыми типами - все тривиально. Максимум - производные иммутабельные типы нужно вытащить из объявлений natives. Со структурами - все совсем не просто: сначала нужно собирать структуру на каждую переменную, а потом сливать структуры с одинаковыми типами полей. 2. Скорее всего будет можно. Эта часть относится исключительно к парсеру. 3. Аналогично. После того, как все будет, парсеры могут быть для любого синтаксиса. (Но, для начала нужно сделать хотя бы один парсер, чтобы точно понять, как оно взаимодействует с остальными частями и зафиксировать API). PS. А тут еще 1.0.4 подвалил - нужно снова переносить в базу все, что было определено в коде.
You think your day was surreal? Try mine.

#34 JNikc

JNikc

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

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

Отправлено 22 June 2009 - 20:52

Python и вправду приятный, раз с него советуют начинать учится кодить, то почему не взять его за основу? Можно скрыть строгую типизацию за деталями синтаксиса и будет "как" динамическая: f = 7.0 // это объявление float, т.к. с точкой i = 7 // это объявление integer, просто цифры s = "ArMani" // массив байтов s[0] // будет 'A', но так как нет char, то наверно нужно взять VKey = i32? *sp = "ArPoint" // sp - указатель на начало строки sp* //содержание Это легко, если типов всего мало. Но со структурами тогда уж можно поступать как обычно: Vector Pos = {x, y, z}

#35 VcSaJen

VcSaJen

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

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


Отправлено 12 July 2009 - 04:55

Я уже это говорил, но сообщение кто-то удалил:
@Listener - Регистрозависимость на лучше убрать, я не знаю такого человека, который бы объявлял три разные переменные Var, var и VAR.

#36 listener

listener

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

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


Отправлено 13 July 2009 - 09:57

Я уже это говорил, но сообщение кто-то удалил:
@Listener - Регистрозависимость на лучше убрать, я не знаю такого человека, который бы объявлял три разные переменные Var, var и VAR.


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

Сообщение отредактировал listener: 23 July 2009 - 16:15

You think your day was surreal? Try mine.

#37 listener

listener

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

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


Отправлено 27 July 2009 - 23:16

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

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

Допустимый максимум - ссылка на массив (в т.ч. многомерный)
Записываться это будет, например, как
int& arrayRef[3][3][4];
Не совсем логично, но
int arrayRef[3][3][4]&;
- получается страшнее.

Сообщение отредактировал listener: 27 July 2009 - 23:17

You think your day was surreal? Try mine.

#38 Chipsman

Chipsman

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

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


Отправлено 28 July 2009 - 06:41

ну да, первый вариант получше будет наверное..

#39 listener

listener

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

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


Отправлено 06 August 2009 - 00:26

Как-то тут тихо и пусто. Такое ощущение, что все уже вовсю освоили С++ (могу только приветствовать) и пользуются ScriptHook-ом.

Составил список, что нужно сделать для релиза. Получилось немного, весь список занимает меньше странички. Крупных вещей осталось три (одна из них - анализ типов в декомпиляторе - даже очень крупная), но, по сравнению с тем, что уже сделано - это уже не страшно. На крайний случай, если в пререлизе нужно будет немного поправить декомпилированный исходник руками, это будет неприятно, но не фатально.

Сейчас воюю с control flow в декомпиляторе. Делать "как правильно" откровенно ломает, поэтому пытаюсь заложиться на то, как работает "родной" кодогенератор. Долго пытался разобраться, где у меня ошибка, в итоге оказалось, что все правильно, только куски до которых не дошло управление, выкинуты.

Соответственно, вопрос: нужно ли декомпилировать код, который гарантированно не исполняется?
Например:
{
   return 1; // все, функция отработала
   // дальше пошел "мертвый код"
  if (v_1) 
	return 0;
  if (IS_CHAR_INJURED (v_0))
	return 1;
  return 0;
}

Еще, я, кажется, понял, зачем нужен хук на START_NEW_SCRIPT. Теоретически, если компилятор будет работать быстро, можно будет грузить скрипты, компилируя их на лету. Для нормальной работы, лучше так не делать, но для отладки - почему бы и нет.

Кстати, о скорости. Декомпиляция всего script.img (366 скриптов, ~15М) из IV/PC, на текущий момент (без анализа данных) занимает на C2D/2.6GHz порядка семи секунд. Script.img от TLaD (218 скриптов, ~3.5M) - порядка четырех секунд. Компиляцию я, по понятным причинам, пока проверить не могу.

Попробовал, прикола ради, подсунуть парочку скриптов от MC:LA. В целом, декомплируется, но есть пара новых конструкций, не встречавшихся в IV. Например, используется команда catch.
You think your day was surreal? Try mine.

#40 Dageron

Dageron

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

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


Отправлено 06 August 2009 - 04:21

Как-то тут тихо и пусто. Такое ощущение, что все уже вовсю освоили С++ (могу только приветствовать) и пользуются ScriptHook-ом.

Ну скриптовые хуки есть не только на C++ :).

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

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

Кстати, о скорости. Декомпиляция всего script.img (366 скриптов, ~15М) из IV/PC, на текущий момент (без анализа данных) занимает на C2D/2.6GHz порядка семи секунд. .

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

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

Script.img от TLaD (218 скриптов, ~3.5M) - порядка четырех секунд. Компиляцию я, по понятным причинам, пока проверить не могу
Попробовал, прикола ради, подсунуть парочку скриптов от MC:LA. В целом, декомплируется, но есть пара новых конструкций, не встречавшихся в IV. Например, используется команда catch.

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




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

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