Skip to content

Latest commit

 

History

History
129 lines (95 loc) · 6.15 KB

File metadata and controls

129 lines (95 loc) · 6.15 KB

main.dat — бинарная база строк

  • Архив: Strings.vfs (1 файл: main.dat, 2 116 764 байта).
  • Загрузчик: CStringDatabase::LoadStrings(IMMLoadObject *pLoad, unsigned long ulBaseID)Game/Engine/StringDatabase.cpp:27.
  • Владеющий интерфейс: IStringDatabase (загружается CEngine при старте, запрашивается по всему коду через GetStringByID(...)).

1. Назначение

main.datлокализованная база текстов для всех строк интерфейса, реплик NPC, описаний предметов и записей дневника. Строки индексируются 32-битными целочисленными идентификаторами; остальной код передаёт эти ID (через IStringDatabase) и разрешает их в UTF-16-строку в момент отображения.

Альфа-сборка содержит ровно один main.dat. Механизм рассчитан на параллельную установку нескольких языковых пакетов — дополнительные .dat-файлы загружались бы с ненулевым ulBaseID для разделения пространств имён.


2. Раскладка на диске

+----------------------+
| u32  ulCount         |   number of (id, string) pairs
+----------------------+
| ENTRY[ulCount]       |   variable size each (see 2.1)
+----------------------+

2.1 ENTRY

u32      ulID            // идентификатор строки (задаётся вызывающей стороной; произвольный)
CEStringW strString      // UTF-16LE-строка с префиксом длины (см. README §Conventions)

CEStringW — широковариантная версия кодировки движка с префиксом длины:

  • байт 0 < 0x80 → длина (в единицах wchar_t, не в байтах) = байт 0.
  • байт 0 ≥ 0x80 → длина = (байт 0 & 0x7F) | (байт 1 << 7).
  • далее length × 2 байт UTF-16LE. Без NUL-терминатора.

Таким образом, строка из N кодпоинтов хранится как префикс длины в 1 или 2 байта плюс 2N байт полезной нагрузки.


3. Поведение загрузчика

CStringReader reader((const char *)pLoad->GetMemoryPointer());
unsigned long ulCount;
reader >> ulCount;
for (unsigned long i = 0; i < ulCount; ++i) {
    unsigned long ulID;
    CEStringW strString;
    reader >> ulID >> strString;
    AddString(ulID + ulBaseID, strString);
}

(StringDatabase.cpp:27-43)

AddString вставляет в std::map<u32, CEStringW>:

  • Первая запись для ID успешна.
  • Последующая запись с тем же ID, но другим значением, молча перезаписывается:20 есть баг: r.first->second == str — это выражение сравнения, а не присваивание — читайте как: последующие записи отбрасываются). На практике конвейер сборки гарантирует уникальность ID, поэтому баг никогда не срабатывает.

Поиск (GetStringByID(...)) возвращает L"?????" для отсутствующих ID (StringDatabase.cpp:117).


4. Раскладка ID в поставочном main.dat

Сами ID — непрозрачные целые числа — на диске нет индекса, указывающего, какой диапазон покрывает какую подсистему. По соглашению конвейер сборки группирует ID в диапазоны:

  • UI: малые числа (подписи кнопок, пункты меню)
  • Предметы: дескрипторы предметов
  • Диалоги: блоки на NPC
  • Дневник: блоки на запись

Авторам модов, которым нужно найти ID для конкретной строки UI, обычно:

  1. Патчат GetStringByID, чтобы логировать каждый промах.
  2. Анализируют существующие .bin-файлы скриптов (см. bin.md), где ID появляются как непосредственные константы в опкодах Push/PushW, подающихся в вызовы скриптового API MessageBox и Diary.

5. Сжатие

Нет. Файл — сырые записи u32 + CEStringW, идущие друг за другом. Общий размер (2.1 МБ) — несжатый UTF-16; драматически сжался бы под zlib, но загружается один раз при старте, и движок не утруждается.


6. Альтернативный загрузчик: текстовый формат

CStringDatabase::LoadStringsFromTextFile (StringDatabase.cpp:46) принимает в качестве альтернативного источника UTF-16LE-файл с BOM. Этот путь документирован отдельно в txt_strings.md и предназначен для рабочих процессов модификации, когда нет желания поддерживать бинарный .dat.


7. Перекрёстные ссылки

  • Текстовый исходный формат: txt_strings.md.
  • Потребители на стороне скриптов: см. [Game/Engine/CEngine.cpp:699] для пути ранней загрузки (LoadStrings вызывается с содержимым Strings.vfs/main.dat).
  • Подписи карты мира в map.md ссылаются на ID из этой базы.