UTF (универсальный формат дерева)
💢 Описание
Формат файла контейнера, используемый для хранения различных ресурсов в Freelancers. Порядок байтов Little-endian.
Freelancer использует UTF в следующих типах файлов:
- .utf (аудиобиблиотека и т. д.)
- .ale (библиотека эффектов частиц)
- .vms (библиотека жестких сеточных буферов)
- .3db (однокомпонентная жесткая модель)
- .cmp (составная жесткая модель)
- .dfm (составная деформируемая модель)
- .sph (простая сферическая модель)
- .txm (библиотека текстур)
- .mat (библиотека материалов)
💢 Заголовок
Файл начинается с блока заголовка, который всегда имеет размер 56 байт.
Имя | Тип | Описание |
---|---|---|
signature | uint32 | Магические байты, строка читается как «UTF ». |
version | uint32 | Всегда 0x101. |
treeOffset | uint32 | Абсолютное смещение байта до блока дерева. |
treeSize | uint32 | Размер дерева в байтах. |
unusedEntryOffset | uint32 | Обычно равна 0. |
entrySize | uint32 | Размер входного байта всегда равен 44. В противном случае Freelancer выйдет из строя. |
namesOffset | uint32 | Абсолютное смещение байта до блока словаря. |
namesSizeAllocated | uint32 | Размер байта словаря, выделенный в памяти. |
namesSizeUsed | uint32 | Размер используемого байта словаря. Должен быть равен или меньше namesSizeAllocated. |
dataOffset | uint32 | Абсолютное смещение байта до блока данных. |
unusedOffset | uint32 | Абсолютное смещение байта к дополнительным данным (не используется). |
unusedSize | uint32 | Дополнительный размер байта данных (неиспользуемый). |
filetime | uint64 | Windows 64-разрядная FILETIME. |
- За заголовком обычно следуют записи, но не всегда, в некоторых файлах перед записями находится словарь.
- Словарь представляет собой соединенную коллекцию строк ASCIIz (строки ASCII, завершающиеся символом NUL).
- Словарь резервирует первую строку как пустую (т. е. первый байт в блоке словаря равен 0x0). Записи с именем нулевой длины игнорируются.
💥 Вход
Каждая запись в блоке дерева занимает 44 байта.
Имя | Тип | Описание |
---|---|---|
nextOffset | uint32 | Смещение к следующему элементу в дереве блоков. |
nameOffset | uint32 | Смещение до имени записи в блоке словаря. |
attributes | uint32 | Атрибуты файловой системы. |
sharingAttributes | uint32 | Атрибуты общего доступа к файловой системе (неиспользуемые). |
childOffset | uint32 | Смещение либо к первому дочернему элементу, либо к данным записи. |
dataSizeAllocated | uint32 | Выделенная длина байта данных. |
dataSizeUsed | uint32 | Фактическая длина используемого байта данных. |
dataSizeUncompressed | uint32 | Длина байта несжатых данных (не используется). |
createTime | uint32 | Временная метка создания файла. |
accessTime | uint32 | Время последнего доступа к файлу. |
modifyTime | uint32 | Время последнего изменения файла. |
- Имя корневой записи дерева должно быть «\», но возможны и другие имена.
- Атрибуты см. в Win32 API dwFileAttributes. Вкратце, это должно быть либо 0x80 для файла, либо 0x10 для папки. Однако не обязательно, чтобы все три байта после первого были нулями, и, фактически, в некоторых стандартных файлах они не являются нулями.
- Когда запись является папкой, childOffset указывает на смещение первого байта дочернего элемента относительно treeOffset в заголовке, а dataSize* — все нули.
- Когда запись является файлом, childOffset указывает на блок данных относительно dataOffset в заголовке, а dataSize* указывает размер файла.
- Временные метки представляют собой 16-битную дату DOS, за которой следует 16-битное время DOS, расположенные следующим образом: https://learn.microsoft.com/en-us/cpp/c-runtime-library/32-bit-windows-time-date-formats
- Игра не требует, чтобы записи в файле были расположены на расстоянии не менее 44 байт друг от друга. В принципе, можно сэкономить на временных метках, если только ни одна запись, связанная с корнем цепочки, не начинается менее чем за 44 байта до EOF. Игра не проверяет эти временные метки на достоверность и не использует их для каких-либо других целей.