UTF (универсальный формат дерева)
📷
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. Игра не проверяет эти временные метки на достоверность и не использует их для каких-либо других целей.