From 0e19660eb5122c8c52d5e909927884ad5c50b813 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Thu, 19 Feb 2026 04:46:23 +0400 Subject: Refactor documentation structure and add new specifications - Updated MSH documentation to reflect changes in material, wear, and texture specifications. - Introduced new `render.md` file detailing the render pipeline process. - Removed outdated sections from `runtime-pipeline.md` and redirected to `render.md`. - Added detailed specifications for `Texm` texture format and `WEAR` wear table. - Updated navigation in `mkdocs.yml` to align with new documentation structure. --- docs/specs/texture.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 docs/specs/texture.md (limited to 'docs/specs/texture.md') diff --git a/docs/specs/texture.md b/docs/specs/texture.md new file mode 100644 index 0000000..5fa1e9d --- /dev/null +++ b/docs/specs/texture.md @@ -0,0 +1,125 @@ +# Texture (`Texm`) + +`Texm` — основной формат текстур движка. + +Связанные страницы: + +- [Material (`MAT0`)](material.md) +- [Wear table (`WEAR`)](wear.md) +- [Render pipeline](render.md) + +## 1. Контейнер + +- Тип ресурса: `0x6D786554` (`Texm`). +- Используется в `Textures.lib`, `LightMap.lib` и других `NRes` архивах. + +## 2. Заголовок + +```c +struct TexmHeader32 { + uint32_t magic; // 'Texm' + uint32_t width; + uint32_t height; + uint32_t mipCount; + uint32_t flags4; + uint32_t flags5; + uint32_t unk6; + uint32_t format; +}; +``` + +## 3. Поддерживаемые форматы + +Базовые форматы: + +- `0` (8-bit indexed + palette) +- `565` +- `4444` +- `888` +- `8888` + +Дополнительные ветки загрузки поддерживают также `556` и `88`. + +## 4. Layout payload + +1. `TexmHeader32` (32 байта) +2. palette `1024` байта, если `format == 0` +3. mip-chain пикселей +4. optional `Page` chunk + +Расчёт ядра: + +```c +bytesPerPixel = + (format == 0) ? 1 : + (format == 565 || format == 556 || format == 4444 || format == 88) ? 2 : + 4; + +pixelCount = sum(max(1, width>>i) * max(1, height>>i), i=0..mipCount-1); +sizeCore = 32 + (format==0 ? 1024 : 0) + bytesPerPixel * pixelCount; +``` + +## 5. `Page` chunk + +```c +struct PageChunk { + uint32_t magic; // 'Page' + uint32_t rectCount; + Rect16 rects[rectCount]; +}; + +struct Rect16 { + int16_t x; + int16_t w; + int16_t y; + int16_t h; +}; +``` + +`Page` задаёт atlas-прямоугольники для выборки под-областей текстуры. + +## 6. Mip-skip политика + +Загрузчик может пропускать первые mip-уровни в зависимости от: + +- `flags5`, +- размеров текстуры, +- количества mip. + +После `mipSkip`: + +- уменьшаются `width/height/mipCount`; +- сдвигается начало пиксельных данных; +- `Page`-координаты пересчитываются в соответствии с новым базовым уровнем. + +## 7. Палитры + +Для части текстур движок связывает палитру по суффиксу имени. + +Практический формат: + +- буква `A..Z` + вариант `""` или `0..9` +- всего `26 * 11 = 286` возможных слотов палитр. + +Невалидные суффиксы нужно считать ошибкой входных данных в инструментах. + +## 8. Кэширование + +Движок ведёт отдельные кэши: + +- общий texture cache; +- lightmap cache. + +Для обычных текстур используется отложенный сбор неиспользуемых слотов (по времени нулевого refcount). + +## 9. Правила writer/editor + +1. Не нормализовать `flags4/flags5/unk6`. +2. Сохранять payload без лишних хвостовых байт. +3. Если есть `Page`, его размер должен быть ровно `8 + rectCount * 8`. +4. Проверять `width > 0`, `height > 0`, `mipCount > 0`. + +## 10. Статус валидации + +- Инварианты `Texm` реализованы в `tools/msh_doc_validator.py`. +- В текущем окружении нет полного игрового набора текстур в `testdata`, поэтому массовая перепроверка не запускалась. -- cgit v1.2.3