RSC

Материал из GTAModding.ru
Перейти к: навигация, поиск

Формат

Ресурсные файлы GTA IV имеют следующий формат:

Заголовок

4 байта - Сигнатура RSC (52 53 43 05)
4 байта - Версия ресурса
4 байта - Флаги

Далее следует сами данные ресурса в запакованном формате. ПК-версия игры использует в качестве алгоритма упаковки - Zlib.

Ресурс содержит два блока памяти - System Memory Segment (CPU) и Graphics Memory Segment (GPU). Размер каждого блока кратен 256. В одном из них хранится сам объект, в другом - используемые данные Direct3D (тексельные, вертексные или индексные буфера).

Каждый ресурс содержит один (и только один) объект, со всеми включенными в него подобъектами. (Например, файл с расширением .WTD содержит в себе объект rage::pgDictionary. При этом, в файле сохраняется не только сама коллекция, но и все включенные в нее объекты текстур, используемые ими хэши, имена и, конечно, пиксельные данные). Все указатели заменяются на смещения в файле. При чтении, смещения заменяются обратно на указатели в памяти.

Любой указатель (число вида 0x5xxxxxxx или 0x6xxxxxxx) преобразуется в 32-битное число. Четыре старших бита в нем - код блока (5 - CPU блок, 6 - GPU блок), младшие 28 - смещение в блоке (для GPU блока возможны случаи, когда структура выравнивается на размер страницы, т.е. младшие 12 бит заменяются нулями, а содержавшееся в них значение используется, например, как идентификатор формата данных).

Таким образом преобразовать любой указатель в значение оффсета можно простой операцией (пример на Delphi и C++):

if (Ptr shr 28 = 5) or (Ptr shr 28 = 6) then Offset:=Ptr and $0FFFFFFF;
if ((Ptr >> 28 == 5) | (Ptr >> 28 == 6)) Offset = Ptr & 0x0FFFFFFF;


Размеры блоков хранятся в RSC-заголовке (параметр "флаги), их можно вычислить следующим образом (пример на Delphi и C++):

  1.  CPUSize:= (Flags AND $7FF) shl (((Flags shr 11) AND $F) + 8); //расчет размера System Memory Segment
  2.  GPUSize:= ((Flags shr 15) AND $7FF) shl (((Flags shr 26) AND $F)+8); //расчет размера Graphics Memory Segment
  1.  CPUSize = (Flags & 0x7FF) << (((Flags >> 11) & 0xF) + 8); //расчет размера System Memory Segment
  2.  GPUSize = ((Flags >> 15) & 0x7FF) << (((Flags >> 26) & 0xF)+8); //расчет размера Graphics Memory Segment

Каждый блок памяти представляет собой набор страниц. В поле флагов кодируется размер и количество страниц. Ресурс должен содержать как минимум одну большую страницу и от нуля до четырех страниц меньшего размера. Любой непрерывный блок не должен пересекать границы страницы.

Допустим, соответствующая часть поля flags, содержит значение 0x1045. Получаем базовый размер страницы 1024 байта (1 << ((0x1145 >> 11)+8)) и количество страниц - 0x45. Верно? Не совсем. На самом деле, будет создано шесть страниц: 4 страницы по 16 килобайт, одна - 4 килобайта и одна - размером в килобайт.

На количество страниц отводится всего 11 бит. Из них старшие семь - это действительно количество страниц (больших страниц), а четрые младших - определяют необходимость выделения страниц меньшего размера (каждый бит отвечает за страницу своего размера). Размер страницы всегда является степенью двойки (если это не так, он округляется вверх).

Полное вычисление всех значений параметра флагов (пример на Delphi и C++):

  1. WORD vpageCount = dwRscFlags & 0x7FF;
  2. WORD largeVpageCount = vpageCount >> 4;
  3. DWORD vpageSize = ((dwRscFlags >> 11) & 15)+8;
  4. WORD ppageCount = (dwRscFlags >> 15) & 0x7FF;
  5. WORD largePpageCount = ppageCount >> 4;
  6. DWORD ppageSize = ((dwRscFlags >> 26) & 15)+8;
  1. {WORD} vpageCount := dwRscFlags and $7FF;
  2. {WORD} largeVpageCount := vpageCount shr 4;
  3. {DWORD} vpageSize := ((dwRscFlags shr 11) and 15)+8;
  4. {WORD} ppageCount := (dwRscFlags shr 15) and $7FF;
  5. {WORD} largePpageCount := ppageCount shr 4;
  6. {DWORD} ppageSize := ((dwRscFlags sgr 26) and 15)+8;

Если загрузка ресурса получается очень простой, то с записью не все так гладко. При записи мало просто посчитать размер блока, нужно еще и найти относительно оптимальную раскладку структур по блокам.

  1. #define RSC_PAGED 0x80000000
  2. #define RSC_COMPRESSED 0x40000000
  3. #define RSC_PHYS_PAGE_COUNT_MASK 0x3C000000
  4. #define RSC_PHYS_TOTAL_PAGES_MASK 0x03FF8000
  5. #define RSC_PHYS_LARGE_PAGES_MASK 0x03F80000
  6. #define RSC_PHYS_S2_PAGE_MASK 0x00040000
  7. #define RSC_PHYS_S4_PAGE_MASK 0x00020000
  8. #define RSC_PHYS_S8_PAGE_MASK 0x00010000
  9. #define RSC_PHYS_S16_PAGE_MASK 0x00008000
  10. #define RSC_VIRT_PAGE_COUNT_MASK 0x00007800
  11. #define RSC_VIRT_TOTAL_PAGES_MASK 0x000007FF
  12. #define RSC_VIRT_LARGE_PAGES_MASK 0x000007F0
  13. #define RSC_VIRT_S2_PAGE_MASK 0x00000008
  14. #define RSC_VIRT_S4_PAGE_MASK 0x00000004
  15. #define RSC_VIRT_S8_PAGE_MASK 0x00000002
  16. #define RSC_VIRT_S16_PAGE_MASK 0x00000001



Версии и типы ресурсов

Тип ресурса определяется расширением (и только расширением), для каждого типа, определен объект, который содержится в этом ресурсе и набор обработчиков для загрузки, инициализации, освобождения, поиска и прочих рутинных операций.

Название Платформа Расширение файла Версия объекта Содержащийся объект Описание
Animation Dictionary Windows *.wad 1 rage::pgDictionary<rage::crAnimation> Коллекция анимаций, содержит преобразованные в ресурсы файлы типа *.anim
Xbox360 *.xad
Texture Dictionary Windows *.wtd 8 rage::pgDictionary<rage::grcTexturePC> Коллекция текстур, содержит преобразованные в ресурсы файлы типа *.DDS
Xbox360 *.xtd 7 rage::pgDictionary<rage::grcTextureXenon>
Physics store ( Bound Dictionary ) Windows *.wbd 32 rage::pgDictionary<rage::phBound> Коллекция содержащая несколько границ (Bound), для нескольких разных объектов.
Xbox360 *.xbd
Drawble Windows *.wdr 110 rage::gtaDrawable Ресурс "простой" модели, помимо информации о самой моделе, информации о шейдерах, также может содержать текстуры используемые только в этой моделе.
Xbox360 *.xdr 109 rage::gtaDrawable
Frag Type Windows *.wft 112 Ресурс "комплексной" модели, кроме собственно самой модели также содержит информацию о границах (Bounds), анимациях и другое...
Xbox360 *.xft 112
HTML Document Windows *.whm 1 rage::CHtmlDocument "HTML" страница внутреннего интернета
Xbox360 *.xhm 1 rage::CHtmlDocument "HTML" страница внутреннего интернета
Drawable Dictionary Windows *.wdd 110 rage::pgDictionary<rage::gtaDrawable> Коллекция содержащая несколько "простых" моделей
Xbox360 *.xdd 109
Static bound ( Bound ) Windows *.wbn 32 rage::pgBaseWrapper<rage::datOwner<rage::phBound>> Ресурс содержит описание границ (Bound) объекта игрового мира, используется для определения физичиских границ объекта.
Xbox360 *.xbn