Elite Games - Свобода среди звезд!
.
ВНИМАНИЕ!
Наша конференция посвящена космической тематике и компьютерным играм.
Политические вопросы и происходящие в мире события в данный момент на нашем сайте не обсуждаются!

  » X3TC Моддинг: obj-файлы и маленькие утилитки |
Конференция предназначена для общения пилотов. Для удобства она разделена на каналы, каждый из которых посвящен определенной игре. Пожалуйста, открывайте темы только в соответствующих каналах и после того, как убедитесь, что данный вопрос не обсуждался ранее.

Search | Conference rules | Album | Register | Pilots list | Profile | Log in to check your private messages | Log in

   Page 1 of 12
Go to page: 1, 2, 3 ... 10, 11, 12  Next    Перейти:   All pages
Поиск в этой теме:
Канал X3: Terran Conflict » Модовый и скриптовый отсек X3: Terran Conflict: «X3TC Моддинг: obj-файлы и маленькие утилитки»
CheckerTwo
 550 EGP


Рейтинг канала: 6(486)
: 103
Posts: 412
Location: Tomsk
Joined: 18 Aug 2004
Добрый день, добрый! Улыбка

Итак, ES переписала свой КC. В результате модернизации KC изменились (и, в общем-то, в лучшую сторону) алгоритмы кодогенерации. Новый КС генерирует байтовые команды. Изменился внутренний формат obj-файлов. Выбросили секцию CTIM. В секции SYMB и VARS остались описания только глобальных процедур и переменных. Все методы и классовые переменные теперь описываются в секции CLAS.

Из неприятностей - уничтожены все имена переменных. В таблицах переменных поля-ссылки на имены остались, но забиты какой-то фигней. Это означает, что разбираться и модифицировать будет теперь сложнее. О совместимости с X3R никакой речи быть не может.


Файл dobj.ini, настройки программы.

ErrExt = ".err"
Ключ задает расширение генерируемого выходного файла ошибок. Все ошибки, замечания и все такое складывается в отдельный файл. Расширение этого файла может быть изменено этим ключом. Ну, вдруг кому-то захочется поменять его на что-то более экзотическое. Для чего делал - уже не помню Улыбка

OutFmt = DEC
Ключ задает вывод имен объектов и числовых констант в десятичной форме или шестнадцатеричной. Допустимые значения DEC или HEX. Это тоже на любителя. Правда возможны нюансы совместимости, когда дизассемблеру задана одна система счисления, а ассемблеру - другая. Желательно выбрать для себя какую-либо из двух и жить на ней.

Tracer = On
Этот ключ включает дополнительный проход дизассемблера. Значительно замедляет работу программы. Однако в процессе трассировки, когда каждая команды выполняется на упрощенной виртуальной машине, позволяет получить более детальную информацию о коде. Например, при включенной трассировке вычисляется значение текущее стека и имена локальных переменных функции, ее аргументов. А также доступность кода.

RenameClass = On
Ключ разрешает подстановку имен классов. Каждый класс в obj-файле имеет уникальный цифровой идентификатор. В таблицах символов (SYMB и CLAS) имена классов не указываются, однако по косвенным признакам были определены многие (но не все). Эти имена сведены в общую таблицу, которая находится в ini-файле в секции [Class_X3TC]. В принципе, если
есть желание, можно изменять эти имена на какие вздумается.

RenameVars = On
Ключ разрешает подстановку имен переменных. С именами переменных в X3TC немного сложнее. В X3R информация об именах хранилась в VARS секциях. Так как obj-движок изрядно по-оптимизировали, egosoft решила, что для работы игрушки эта информация не нужна. В общем-то резонно, но для разбора кода теперь придется задавать имена переменных ручками.

OutExtern = On
Этот ключ (если включен) разрешает вывод в asm-файл большого числа строк, начинающихся директивой .extern, в которых перечислены все встретившиеся API-функции. Для простого анализа кода можно и запретить этот вывод. Для ассемблера эта информация нужна.

OutDASM = ".out", On
OutDEF = ".def", On
OutASM = ".asm", On
OutSYMB = ".sym", On
OutVARS = ".var", On
OutPTCH = ".pct", On
OutSTRG = ".str", On
Этот список ключей разрешает/запрещает вывод информации в текстовые файлы. Некоторые файлы содержать только служебную информацию - так называемый дамп таблиц и в большинстве случаев не нужны. Описание этих файлов приводятся ниже... Этими ключами можно задать расширения выходных файлов. А также разрешить/запретить генерацию указанного файла.

OutMOD = "output\", "T", ".txt", Off
out-файл, получаемый при дизассемблировании основного x3store.obj весьма велик. Найти в нем что-либо довольно сложно. Причем функции могут быть разбросаны по всему файлу (это для global). Если исследуется только какая-то небольшая часть, один из объектов, может оказаться удобным использовать данную фичу - вывод каждого объекта в отдельный файл. Имена файлов задаются номером модуля, можно дополнительно указать директорию вывода, префикс имени файла и его расширение файла.

RemarkNoUse = On
RemarkIfConst = On
Как показала практика на примере X3, obj-код может содержать большой объем недоступных для исполнения движком команд, процедур и прочее. Может встречаться код, программно закоментаренный (if (0) {...} ). Чтобы было легче разбираться, можно использовать ключи RemarkNoUse и RemarkIfConst, которые разрешают дизассемблеру комментарить недоступный код. Эта фича доступна только при включенной трассировке программы. Недоступный при выполнении код в asm-файл будет закоментарен.

UnsafeCmd = On
Этот ключ включает фактически, маленький оптимизатор, который был встроен в дизассемблер в X3R для получения более оптимизированного кода для XC. При включенном трассировщике, дизассемблер комментарит конструкции вида "push / cmd / pop". Где, cmd - это одна из следующих команд add, sub, mul, div, mod, or, and, xor. Последовательность команд, приведенная выше может генерироваться компилятором KC, но не несет какой-либо полезной смысловой нагрузки.

Немного про секцию имен [Class_X3TC]
В секции задаются имена классов и имена переменных. Примерно так, как это было в дизассемблере для X3R. Но добавилось определение имен переменных. Имена некоторых переменных Shaddie уже нашел. Указанная информация об именах переменных в dobj.ini действительна для obj-файлов версии 1.1.2.

Code:

Имя класса определяется следующим образом:
  <числовой_идентификатор> = "имя_класса"

Имя переменоой может быть задано так:
  <числ_ид_класса>, <числ_ид_переменной> = "имя_переменной"


Идентификатор класса "0" используется для определения глобальных функций и переменных и не является номером класса как таковым.

Например:
Code:

0    = "global"           ; с таким именем будут все глобальные переменные и функции
0, 0 = "FONT_OCR"         ; переменная с индексом 0
0, 1 = "FONT_LARGE"       ; переменная с индексом 1
0, 2 = "gs_TextFileTable" ; переменная с индексом 2
...



Форматы выходных файлов.

out - файл содержит полный дизассемблерный листинг, содержащий информацию об адресах команд, бинарном коде, стеке, командах и прочее...

def - файл содержит только заголовки классов и функций. Может быть использован для быстрого поиска нужного класса и разбора иерархии классов.

asm - файл содержит все, что нужно ассемблеру для компиляции программы.

sym - файл
Этот файл содержит информацию из таблиц символов - функциях. Файл разбит на несколько частей. В первой части - список всех объектов. Например, ниже показан кусочек такого файла.

(Attension! нижеследующая информация выдрана с разных obj-файлов, разных мест, поэтому с реальными файлами цифровая информация может не совпадать. Но, для примера - самый раз)

Code:

OBJECTS 24  <<-- число объектов в obj-скрипте

obj  parent   | vars funcs | object-name
0000 FFFFFFFF |   28    25 | global
006C FFFFFFFF |    2     1 | TObj108
0133 00000134 |    1    34 | DIRECTOR
 ^      ^         ^     ^      ^
 |      |         |     |      |
 |      |         |     |      +--------- имя объекта
 |      |         |     +---------------- количество функций в объекте
 |      |         +---------------------- количество переменных в объекте
 |      +-------------------------------- id родителя (если нет, то FFFFFFFF)
 +--------------------------------------- id класса

Если подходить строго, то объекта с id равным 0 не существует. Точнее это не объект, это глобальные функции и переменные. Но выводить отдельной строчкой было как-то некрасиво, поэтому вот так. Улыбка

Code:

SYMB 6341
obj  parent   |   # addr     stack    narg     strg     | name
0282 00000281 |   8 000EBE68 00000001 00000000 0000F166 | GetMousePriority
0294 FFFFFFFF |   0 0001F913 00000001 00000001 00005C9F | QueryEffectiveValue
0294 FFFFFFFF |   1 0001F918 00000001 00000000 00005CB3 | PeekRefString
0294 FFFFFFFF |   2 0001F91D 00000001 00000000 00004BA7 | Destruct
0295 00000294 |   0 0001F922 00000002 00000001 00004A29 | Create
0295 00000294 |   1 0001F945 00000001 00000001 00005C9F | QueryEffectiveValue
 ^      ^         ^     ^       ^        ^        ^       ^
 |      |         |     |       |        |        |       +- имя функции
 |      |         |     |       |        |        +--- указатель на строку
 |      |         |     |       |        +------------ число арг. функции
 |      |         |     |       +--------------------- максимальный размер стека
 |      |         |     +----------------------------- адрес начала функции
 |      |         +----------------------------------- номер функции в таблице
 |      +--------------------------------------------- id родителя (если нет, то FFFFFFFF)
 +---------------------------------------------------- id класса


var - файл
Этот файл содержит информацию из таблиц символов - переменных. Ниже показан кусочек такого файла.
Code:

VARS 425  <<-- общее число переменных

obj  parent   |   # initval  type      strg    | name
0000 FFFFFFFF |   0 00000000 00000001 49076002 | FONT_OCR
0000 FFFFFFFF |   1 00000000 00000001 49076002 | FONT_LARGE
 ^      ^         ^     ^       ^        ^        ^
 |      |         |     |       |        |        |
 |      |         |     |       |        |        +--- имя переменной
 |      |         |     |       |        +------------ указатель на строку
 |      |         |     |       +--------------------- тип переменной
 |      |         |     +----------------------------- инициализация
 |      |         +----------------------------------- номер переменной в классе
 |      +--------------------------------------------- id родителя (если нет, то FFFFFFFF)
 +---------------------------------------------------- id класса


ptc - файл
В этом файле содержится информация о патчах. Как работает - никто не знает. Улыбка Ниже приводятся несколько строк из ptc-файла, так для примера...
Code:

PTCH
Length section = 41556
Count sections = 7

# Patch 1  Created : 28.08.2008 19:15:22
00000C00 | 000010B5
00000C9A | 00000000


str - файл
В секции STRG (слегка зашифрованной) хранятся строковые ресурсы. В том числе и имена функций.
Code:

STRG
00000001 : CheatEquip
0000000C : AddWare
00000014 : GetNumUpgrades



Ассемблер.
Описание подготовлю чуть позже, пока на работе запарки. Игрушки пока нет, попробовать и все перепроверить нет возможности, но код, сгенеренный dobj-ем этот ассемблер компилит. Улыбка

Резюме
Во вложении - версии ассемблера и дизассемблера. Думаю, что некоторые тонкости реализации игрушки станут более понятны после разбора obj.

Ассемблер - версия x04.12b
Дизассемблер - версия x04.15b

Пробуйте.. Улыбка

do4_15b.zip
 Description:
Дизассемблер. Версия исключительно для X3TC.
 Filename:  do4_15b.zip
 Filesize:  110.82 KB
 Downloaded:  2202 Time(s)
xa4_12b.zip
 Description:
Небольшой ассемблер. Версия исключительно для для X3TC.
 Filename:  xa4_12b.zip
 Filesize:  123.03 KB
 Downloaded:  1958 Time(s)


Last edited by CheckerTwo on 14:29 15-12-2014; edited 17 times in total
Last edited by Executor on 21:50 11-11-2008; edited 1 time in total
    Posted: 23:11 08-11-2008   
Darth Revan
 345 EGP


Рейтинг канала: 3(30)
: 42
Posts: 349
Location: Belarus Prime
Joined: 01 Feb 2006
Пока не понял назначения параметров у команд xjump и switch. Идеи есть?
    Posted: 22:28 08-01-2009   
klop711
 80 EGP


Рейтинг канала: 3(36)
: 24
Posts: 41
Location: Minsk
Joined: 19 Aug 2007
Darth Revan wrote:
Пока не понял назначения параметров у команд xjump и switch. Идеи есть?

примерно так:

Code:
79 <US:A> <US:B>
   <UL:OFS>   ; others
   <SL:C0> <UL:OFS>   ; case(C0)
   <SL:C1> <UL:OFS>   ; case(C1)
   <SL:C2> <UL:OFS>   ; case(C2)
   ...
где:
<US:A> - число кейзов (случай их монотонного возрастания, u_int_16) - быстрый вариант без полного перебора;
<US:B> - число кейзов (любой порядок значений, u_int_16) - полный перебор;
<SL:Cx> - значение кейза (s_int_32);
<UL:OFS> - адреса (u_int_32).

присутствует либо <US:A>, либо <US:B> второй при этом равен нулю.

---------------------------

Code:
78 <US:A> <SL:C0>
   <UL:OFS>   ; others
   <UL:OFS>   ; case(C0)
   <UL:OFS>   ; case(C0+1)
   <UL:OFS>   ; case(C0+2)
   ...
- более экономный Ничего не понимаю... вариант случая монотонного инкремента значений кейзов.
<SL:C0> - это 32-битное знаковое целое, а не два 16-битных числа, как их разбирает "dobj"!

---------------------------

кстати Есть предложение! после pushf (код 0x0A) идёт именно double (64 bit по IEEE754) - неплохо бы его сразу и переводить т.е., например:
Code:
xxxxxxxx:   0A +1.0E-5   ;

вместо:
Code:
xxxxxxxx:   0A 3EE4F8B5 88E368F1   ;


P.S. всё высосано "из пальца" и нуждается в проверке.
    Posted: 03:48 11-01-2009   
Darth Revan
 345 EGP


Рейтинг канала: 3(30)
: 42
Posts: 349
Location: Belarus Prime
Joined: 01 Feb 2006
klop711 wrote:
примерно так: ...
Вроде ты прав. Супер! Начинаю писать xasm->xc. Будет xc код - будет легче проверить, но очень похоже на правде.

klop711 wrote:
SL:C0> - это 32-битное знаковое целое, а не два 16-битных числа, как их разбирает "dobj"!
Гениально. Вау!

klop711 wrote:
Кстати после pushf (код 0x0A) идёт именно double (64 bit по IEEE754) - неплохо бы его сразу и переводить
Ты прав. В X2/X3 я просто позжно догадался, что такое команда unknown. В xc->xasm ввёл double, а вот в xasm->xc - нет.
    Posted: 16:07 11-01-2009   
Chem
 780 EGP


Скрипт-мастер
Рейтинг канала: 6(498)
: 248
Posts: 4751
Location: Киев
Joined: 08 Jan 2007
Darth Revan wrote:
Начинаю писать xasm->xc

Ура! Супер!
_________________
Умножим энтропию на 0 :-)
    Posted: 17:06 11-01-2009   
CheckerTwo
 550 EGP


Рейтинг канала: 6(486)
: 103
Posts: 412
Location: Tomsk
Joined: 18 Aug 2004
klop711 wrote:
примерно так:

Спасибо! Улыбка

Поправил дизассемблер и ассемблер. Изменил команды xjump и pushf. Исправил ошибки в ассемблере при генерации типов переменных.

Команда pushf, которая ранее была обозвана double, понимает пока только вещественное число. Т.е. нельзя вставить выражение для вычисления. Думаю будет время - доработаю этот момент.

Формат команды xjump - как и писал klop711 - имеет 2 аргумента.

Подправленные версии в первом посте.
    Posted: 19:01 02-02-2009   
ULiX
 320 EGP


: 146
Posts: 573
Location: Комсомольск на-Амуре
Joined: 12 Jul 2005
Darth Revan wrote:
Пока не понял назначения параметров у команд xjump и switch. Идеи есть?

Необходимо лишь сверить фрагмент ASM с исходным фрагментом KC.
Доступ к исходникам имеется например у меня... Хотя я и подписал соглашение о неразглашении, но я ведь не собираюсь вам все исходники сливать.
Нужно определиться в какой конкретно функции, какого класса используется интересующий фрагмент структуры switсh-case, а там логически домыслим.

to Darth Revan
Я понимаю, что ты придерживаешься принципа не делать XC похожим на оригинальный KC синтаксис. Но было бы очень здорого, если бы можно было использовать и оригинальный KC синтаксис при написании модов. Для поддержки совместимости можно применять какие-нибудь метакоманды для переключения между KC и XC синтаксисами (как это сделано для вставок на Xасме). Также ввести глобальные метакоманды в начале программы, которая определит тип синтаксиса.

Очень хочется писать исходники модов таким образом, чтоб их можно было предложить и для внедрения в игру официально. Кроме того, можно с сайта эгософт скачивать давально не плохие заготовки функций для реализации своих задач. Это ускоряет работу и позволяет создавать очень приличные моды с исходником на несколько десятков строк исходного кода.

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

Есть заготовки на сайте ЭГОСОФТ написанные другими пилотами. В них есть вполне рабочие моменты, которые можно взять за основу, или скопировать нужные блоки и переделать их для своих нужд. Но на данный момент "переделка" занимает больше времени, чем написание по новой, так как приходится проследить, чтоб все моменты соответствовали нужному синтаксису. Убрать определения переменных разных типов и привести их к var, переделать определение массивов и другие структуры.

Если есть необходимость в примерах исходников KC, или есть вопросы по представлению в KC различных структур и команд, могу подсобить. Но естественно выкладывать исходники в открытом виде я не собираюсь. Как никак шпионы Эгософт имеются везде, а я терять свои права не хочу.

Очень буду благодарен, если мою просьбу удастся удовлетворить.
_________________
Новое ещё не значит лучшее
    Posted: 08:18 20-04-2009   
DIMOSUS.X
 997 EGP


Рейтинг канала: 8(921)
: 188
Posts: 3252
Location: Vilnius/Minsk
Joined: 06 Aug 2008
Подскажите, насколько я понимаю в обже стоит ограничемие на количество обьектов в бод файлах сцен - 999. Можно ли увеличить это значение?
_________________
Даже ежики ежиков могут с трудом,
Иначе бы ежики были кругом.
    Posted: 10:43 21-04-2009   
зодчий
 155 EGP


Рейтинг канала: 4(81)
: 18
Posts: 143
Location: москва
Joined: 03 Jul 2009
DIMOSUS.X wrote:
Подскажите, насколько я понимаю в обже стоит ограничемие на количество обьектов в бод файлах сцен - 999. Можно ли увеличить это значение?

незнаю ...да и чем те 999 мало ??? если обьекты в сценах
с мешем и повторяются много раз, просто приатач их в максе вместе с лодами ))или у тя фонарики там на елочку ???
извини просто не совсем понял природу вопроса ))
    Posted: 02:57 05-07-2009   
DIMOSUS.X
 997 EGP


Рейтинг канала: 8(921)
: 188
Posts: 3252
Location: Vilnius/Minsk
Joined: 06 Aug 2008
Два слова: карта галактики
_________________
Даже ежики ежиков могут с трудом,
Иначе бы ежики были кругом.
    Posted: 03:04 05-07-2009   
зодчий
 155 EGP


Рейтинг канала: 4(81)
: 18
Posts: 143
Location: москва
Joined: 03 Jul 2009
вот здесь я несведущ ...может что то скриптами потом расставить
удасться ??
    Posted: 03:33 05-07-2009   
Boron Friend
 830 EGP


Рейтинг канала: 5(248)
: 263
Posts: 1222
Location: Kingdom End
Joined: 24 Dec 2004
зодчий wrote:
может что то скриптами потом расставить
удасться ??

одно слово: обж Гы-гы
    Posted: 15:43 05-07-2009   
AlexYar
 1945 EGP


Рейтинг канала: 4(81)
: 325
Posts: 33144

Joined: 26 Oct 2003
Кто в курсе, DarthRevan писал xa2c и хс для х3тс или нет?
Если да, то дайте ссылки, пжлст.
    Posted: 21:01 05-09-2009   
DIMOSUS.X
 997 EGP


Рейтинг канала: 8(921)
: 188
Posts: 3252
Location: Vilnius/Minsk
Joined: 06 Aug 2008
Кому-нибудь удалось скомпилировать обж X3TC?
Сколько не возился с xa4_04a, ни как не получается Рыдания.
_________________
Даже ежики ежиков могут с трудом,
Иначе бы ежики были кругом.
    Posted: 19:51 28-10-2009   
CheckerTwo
 550 EGP


Рейтинг канала: 6(486)
: 103
Posts: 412
Location: Tomsk
Joined: 18 Aug 2004
С новыми (перекомпиленными) обжами игрушку не запускал. На выходных, если шеф даст продыху - посмотрю. Чуть подробнее опиши что и как не получается..
    Posted: 17:20 30-10-2009   
DIMOSUS.X
 997 EGP


Рейтинг канала: 8(921)
: 188
Posts: 3252
Location: Vilnius/Minsk
Joined: 06 Aug 2008
Декомпилил обж, затем на натравливал асемблер на листинг. Полученный результат подсовывал игре, и как результат - мертвое зависание при начале новой игры.

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

Code:

                                              .title     x3story
                                              .radix     16d
                                              .loadobj   "x3story.obj"

                                              .section   code, abs
$ = 0000535Eh
                 jump       L000053BA


                                              .end


Результат - зависание компилера.


З.Ы. Спасибо за твой титанический труд в ковырянии обжа и написании диз\асемблера Улыбка
_________________
Даже ежики ежиков могут с трудом,
Иначе бы ежики были кругом.

Last edited by DIMOSUS.X on 22:16 30-10-2009; edited 2 times in total
    Posted: 20:39 30-10-2009   
CheckerTwo
 550 EGP


Рейтинг канала: 6(486)
: 103
Posts: 412
Location: Tomsk
Joined: 18 Aug 2004
DIMOSUS.X wrote:
Результат - зависание компилера.

Мда. Накосячил. Я не при чем...

В первом посте - поправленные версии.
Ассемблер - версия x04.05a
Дизассемблер - версия x04.06a
    Posted: 04:27 31-10-2009   
DIMOSUS.X
 997 EGP


Рейтинг канала: 8(921)
: 188
Posts: 3252
Location: Vilnius/Minsk
Joined: 06 Aug 2008
Тоесть теперь будет работать полная песборка обжа Улыбка ?
_________________
Даже ежики ежиков могут с трудом,
Иначе бы ежики были кругом.
    Posted: 08:42 31-10-2009   
DeS(Vladik)
 





Непонял как изменять *.obj файлы.
Мне нужно изменить класы кораблей(М0-М8,добавить М9 и М10) какой файл использовать неподксажете??
    Posted: 19:56 09-11-2009   
DIMOSUS.X
 997 EGP


Рейтинг канала: 8(921)
: 188
Posts: 3252
Location: Vilnius/Minsk
Joined: 06 Aug 2008
Вобщето классы кораблей зашыты в ехе, в обже их функции.
_________________
Даже ежики ежиков могут с трудом,
Иначе бы ежики были кругом.

Last edited by DIMOSUS.X on 21:49 09-11-2009; edited 1 time in total
    Posted: 20:07 09-11-2009   
Канал X3: Terran Conflict -> Модовый и скриптовый отсек X3: Terran Conflict: «X3TC Моддинг: obj-файлы и маленькие утилитки»
Go to page: 1, 2, 3 ... 10, 11, 12  Next    Перейти:   All pages
  
Display posts from previous: 
View previous topic | View next topic |
К списку каналов | Наверх страницы
Цитата не в тему: Какой нах канал сайта? Такие вопросы тока в ЖК! Железный Канал! Медаль ведь железная - значит, в ЖК! (void*)

  » X3TC Моддинг: obj-файлы и маленькие утилитки |
Каналы: Новости | Elite | Elite: Dangerous | Freelancer | Star Citizen | X-Tension/X-BTF | X2: The Threat | X3: Reunion | X3: Terran Conflict | X Rebirth | X4: Foundations | EVE Online | Orbiter | Kerbal Space Program | Evochron | VoidExpanse | Космические Миры | Онлайновые игры | Другие игры | Цифровая дистрибуция | play.elite-games.ru | ЗВ 2: Гражданская война | Творчество | Железо | Игра Мечты | Сайт
   Дизайн Elite Games V5 beta.18