#1 12-12-2008 00:30

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Ресурсы и структуры GTA IV

1. Система ресурсов в целом

Ресурсы в IV, отличаются от предыдущих игр серии не сколько форматом, сколько подходом. Если для объектов RenderWare была определена какая-то структура, тэги и блоки, то в IV этого нет.То что скрывается в блоке, начинающемся с 'RSC\5' - это просто два непрерывных блока памяти, упакованных и сохраненных на диске.

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

(здесь должна быть диаграмка, но прямо сейчас мне лень ее рисовать)

Следствие один: чтобы прочесть ресурс - достаточно одной операции чтения.
Следствие два: описание структуры в памяти, автоматически является форматом ресурса.

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

Размеры блоков хранятся в RSC-заголовке (более подробно, это будет описано позже). Пока же, просто приведу вывод моего маленького распаковщика:

C:\...cuments\My Work\_reverse engineering\gta\_gta4_data\rscexw>rscexw.exe w_bat.wdr w_bat.wdru
Input file: w_bat.wdr
Loaded resource file: version=110, CPU_size = 0x1000, GPU_size = 0x3000
Output file: w_bat.wdru
in = 6132, out = 16384
OutSize = 16384, err = 0
Complete.

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

wad: rage::pgDictionary<rage::crAnimation>
wbd: rage::pgDictionary<rage::phBound>
wbn: rage::pgBaseWrapper<rage::datOwner<rage::phBound>>
wbs: rage::grbTargetManager
wdd: rage::pgDictionary<gtaDrawable>
wdr: gtaDrawable
wft: gtaFragType
whm: CHtmlDocument
wtd: rage::pgDictionary<rage::grcTexture>

PS. Как можно понять по приведенному списку, R* использует достаточно продвинутый C++. Поэтому, если возникнут вопросы шаблонам, оператору new, множественому наследованию и т.д. - лучше создать отдельную тему "Вопросы по C++" и спросить там.

Как обычно, вопросы, дополнения и исправления приветствуются.

Offline

#2 18-12-2008 22:27

Capushon
Registered: 13-08-2006
Posts: 350
Website

Re: Ресурсы и структуры GTA IV

@listener -
Какое назначение файла GTA4\common\data\Scenarios.dat ?


Сначала ты надежда и гордость,
Потом о спину ломают аршин. (c)БГ

Offline

#3 19-12-2008 01:02

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

@Capushon - Насколько я понял - оследовательности действий педов (более продвинутая версия PedAttractor). Т.е. можно создавать не просто абстрактных педов, но и сразу назначать им сложные осмысленные действия. (Без необходимости кодить новый CTaskComplex...)

Разберу точнее - обязательно расскажу

Offline

#4 19-12-2008 03:55

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: Ресурсы и структуры GTA IV

Он отвечает за "оживление" города разными случайными сценками типа когда водители чинят свои машины, рабочие что-то делают, полиция гонится за нарушителями и т.д.

Подробнее здесь:
http://www.gtamodding.com/index.php?title=Scenarios.dat
http://www.gtaforums.com/index.php?showtopic=380874

Offline

#5 20-12-2008 17:04

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Пока у меня есть свободная минутка - несколько простых и повсеместно встречающихся структур.
В оригинале, большая часть описываемого - не struct, а class. Я здесь объявляю все, как структуры, чтобы не описывать права доступа (public/protected/private), по которым у меня все равно нет информации.
Аналогично, для краткости я опускаю нэймспейсы (вместо rage::grcTexture пишу просто grcTexture и т.д.).

template<typename T> struct CSimpleCollection { // size = 8
	T * 	pData;	// +0 массив элементов типа T
	WORD    wCount;	// +4 количество занятых элементов массива
	WORD	wSize;	// +6 общее количество элементов масива
};

template<typename T> struct CPtrCollection { // size = 8
	T**	ppData;	// +0 массив указателей на элементы типа T 
	WORD    wCount;	// +4 количество занятых элементов массива
	WORD	wSize;	// +6 общее количество элементов масива
};

Если внутри RSC виден указатель (число вида 0x5xxxxxxx или 0x6xxxxxxx), за которым следуют два одинаковых WORD - с очень большой вероятностью, это та или иная коллекция.
Мне встречались коллекции, у которых wCount больше wSize. Предположительно, это какой-то глюк экспорта ресурса. Влюбом случае, количество элементов берется из wCount. wSize нужен только коду, при добавлении новых элементов в коллекцию.
Для CPtrCollection, нужне не забывать проверять значения указателей на нулевое значение.

datBase. Это общий предок для большинства объектов RAGE. Возможно, он содержал какую-то диагностику или трассировку, но в релизный файл это не попало.
Внутри ресурса, в единственном поле этой структуры (и всех ее потомков) содержится относительно произвольное число (например, 0x695384). Это остатки от экспортера ресурсов, а именно - указатель на VMT этого класса в памяти редактора ресурсов).
При экспорте ресурсов, в этом поле может быть записано произвольное значение.

struct datBase { // size = 4
	// ВНИМАНИЕ! Это поле не требуется явно описывать, если в структуре есть хотя бы один виртуальный метод - его автоматически добавит компилятор
	DWORD	__vmt;	// +0 указатель на таблицу виртуальных методов. 
};

pgBase - объект, который может взаимодействовать с менеджером памяти.
pMap указывает на массив из 128 DWORD (512 байт). Первый элемент массива должен быть нулевым.

struct pgBase : public datBase { // size = 8
	DWORD * pMap;	// +4 указатель на карту распределения памяти
};

pgDictionary - коллекция именованных объектов. Многие ресурсы (wad, wdd, wtd), представляют собой pgDictionary.
Сам pgDictionary не содержит имен. От них берутся только хэши (а имена есть только в содержащихся объектах).
Хэши должны быть отсортированы по возрастанию. Порядок хэшей должен совпадать с порядком элементов в m_data.

template<struct T> struct pgDictionary : public pgBase { // size = 0x20
	pgDictionary<T> *	m_pParent; 	// +8 dictionary более высокого уровня (внутри ресурса - обычно NULL)
	DWORD			m_dwUsageCount;	// +0x0C количество ссылок на объект. Как только доходит до нуля, объет освобождается (внутри ресурса содержит 1)
	CSimpleCollection<DWORD> m_nameHashes;	// +0x10 коллекция хэшей имен содержащихся объектов. 
	CPtrCollection<T>	m_data;		// +0x18 сами элементы, содержащиеся в словаре
};

Last edited by listener (20-12-2008 19:03)

Offline

#6 20-12-2008 18:19

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

И еще немножко. То, что у меня накопано по форматам моделей (накопано мало, выкладываю то, что есть. Как будет еще - допишу/поправлю).
Я опускаю некоторые промежуточные классы не критичные для чтения ресурсов (например, я не описываю отдельно grcVertexBuffer, потому что, в PC версии везде используется унаследованный от него grcVertexBufferD3D)

По смещению 0 в .wdr находится объект gtaDrawable, в .wdd - pgDictionary<gtaDrawable>

struct rmcDrawable : public pgBase {	// size = 0x80
	grmShaderGroup *	m_shaderGroup;	// +8
	void *			_fC;		// +0xC - указатель на неразобранный объект размером 0x40 байт
	BYTE			__unknown1[48];	// +0x10  -- не разобрано
	CPtrCollection<grmModel> * m_models[4];	// +0x40 - массив из четырех указателей на коллекции моделей (ВНИМАНИЕ! Еще раз: массив указателей на коллекции указателей на модели)
	BYTE			__unknown2;	// +0x50  -- не разобрано
};

struct gtaDrawable : public rmcDrawable {	// size = 0x88
	CSimpleCollection<CLightAttr>	m_lightAttrs;	// +0x80
};
struct grmModel : public datBase {	// size = 0x1C 
	CPtrCollection<grmGeometry>	m_geometries;	// +4 
	void * 	_fC;
	void * 	_f10;
	BYTE	_f14;
	BYTE	_f15;
	BYTE	_f16;
	BYTE 	_f17;
	BYTE	_f18;
	BYTE	_f19;
	WORD	_f1A;
};

struct grmGeometry : public datBase {	// size = 0x4C
	DWORD	_f4;	// +4
	DWORD	_f8;
	grcVertexBufferD3D *	m_vertexBuffers[4];	// +0xC - четыре указателя на объекты вертексных буферов (неиспользуемые указатели - NULL)
	grcIndexBufferD3D	*m_indexBuffers[4];	// +0x1C - аналогично, индексные буфера
	DWORD	m_dwIndexCount;  // +0x2C
	DWORD	m_dwFaceCount; // +0x30
	WORD	m_wVertexCount; // +0x34
	WORD	m_wIndicesPerFace;	// +0x36
	void * 	_f38;   
	WORD	m_wVertexStride;
	WORD	_f3E;
	DWORD	_f40;
	void *	_f44;
	DWORD	_f48;
};
struct grmShaderGroup : public datBase { // size = 0x50
	pgDictionary<grcTexture> *	m_txd;		// +4
  	CPtrCollection<grmShaderFx> 	m_shaders;	// +8
	CPtrCollection<void> 			_f10;		// коллекция неизвестных структур
	CPtrCollection<void> 			_f18;		// коллекция неизвестных структур
	CPtrCollection<void> 			_f20;		// коллекция неизвестных структур
	CPtrCollection<void> 			_f28;		// коллекция неизвестных структур
	CSimpleCollection<DWORD> 		_f30;
	CSimpleCollection<CSimpleCollection<DWORD>> 	_f38;     
	CSimpleCollection<DWORD> 		_f40;
	CSimpleCollection<DWORD> 		_f48;
};

UPD (2008-12-21): добавлено несколько полей от aru, добавлен grmShaderGroup

Last edited by listener (21-12-2008 21:13)

Offline

#7 20-12-2008 18:20

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Объекты буферов разобраны практически полностью:

struct grcVertexBufferD3D : public datBase { // size = 0x20
	WORD	m_wVertexCount;	// +4 - количество вертексов
	BYTE	m_bLocked;	// +6 - флаг (см. описание IDirect3DVertexBuffer9::Lock)
	BYTE	_align1;	// +7 - выравнивание
	BYTE * 	m_pLockedData;	// +8 - указатель на locked buffer, в файле совпадает с m_pVertexData
	DWORD	m_dwVertexSize;	// +0xC - размер вертекса в байтах
	void *	_f10;		
	DWORD	m_dwLockThreadId;// +0x14 - thread id, потока использующего буфер (в файле, 0)
	BYTE *	m_pVertexData;	// +18 - уазатель на сами данные (в GPU seg)
	IDirect3DVertexBuffer9 * piVertexBuffer;	// +0x1C - указатель на соответствущий D3D объект (в файле, 0)
};

struct grcIndexBufferD3D : public datBase { // size = 0x10
	DWORD	m_dwIndexCount;	// +4
	WORD *	m_pIndexData;	// +8
	IDirect3DIndexBuffer9 * piIndexBuffer; // +0xC
};

Offline

#8 21-12-2008 13:13

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: Ресурсы и структуры GTA IV

Сообщения этой темы выделены в отдельное обсуждение
Черно-белый фильтр при аресте и смерти

Offline

#9 01-01-2009 20:24

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: Ресурсы и структуры GTA IV

Полный список native functions в GTA IV PC
http://public.sannybuilder.com/GTA4/gta_natives_pc.txt

Там больше сотни новых функций по сравнению с боксом.

Offline

#10 07-01-2009 04:13

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Виртуальняе методы класса fiDevice (и его сабклассов)

class fiDevice  {
public:
    fiDevice () {}
    virtual ~fiDevice () {}

    virtual HANDLE  open (char * pszName, bool bReadonly) = 0;	                            // m4
    virtual HANDLE  openBulk (char * pszName, DWORD * ) { return INVALID_HANDLE_VALUE; }	// m8
    virtual HANDLE  create (char * pszName) { return INVALID_HANDLE_VALUE; }                // mC
    virtual HANDLE  _m10 (char * pszName) = 0;  
    virtual int     read (HANDLE hFile, void * pBuffer, int nCount) = 0;                    // m14
    virtual int     readBulk (HANDLE hFile, int nOffset, int nOffsetHight, void * buf, int nLength) { return -1; }	// _m18   
    virtual int     writeBulk (HANDLE hFile, int nOffset, int nOffsetHigh, void * buf, int nLength) { return -1; }
    virtual int     write (HANDLE hFile, void * pBuffer, int nCount) = 0;
    virtual int     seek (HANDLE hFile, int nPos, int nWhence) = 0;	// _m24
    virtual int     close (HANDLE hFile) = 0;
    virtual int     closeBulk  (HANDLE hFile) { return -1; }	// _m2C
    virtual int     filelength (HANDLE hFile);	    // _m30
    virtual int     _m34 (HANDLE) { return 0; }
    virtual bool    unlink (char * pszName) { return false; }
    virtual bool    rename (char * pszOldName, char * pszNewName) { return false; }
    virtual bool    mkdir (char * pszName) { return false; }
    virtual bool    rmdir (char * pszName) { return false; }
    virtual __int64 filelengthLong (char * pszName);	// get length of the contained file
    virtual __int64 getFileTime (char * pszName) = 0;                                               // m4C
    virtual bool    setFileTime (char * pszName, int nFileTime, int nFileTimeHigh) = 0;             // m50
    virtual HANDLE  findFirst (char * pszName, void * pResults) { return INVALID_HANDLE_VALUE; }    // m54
    virtual bool    findNext (HANDLE hFind, void * pResults) { return false; }                      // m58
    virtual int     findClose (HANDLE hFind) { return -1; }                                         // m5C
    virtual bool    truncate (HANDLE hFile) { return false; }                                       // m60
    virtual DWORD   getFileAttrs (HANDLE hFile) { return 0xFFFFFFFF; }                              // m64
    virtual bool    setFileAttrs (HANDLE hFile, DWORD dwAttrs) { return false; }                    // m68
    virtual int     getResourceVersion (char * pszName, DWORD _a4, DWORD * dwFlags);	            // m6C
    virtual HANDLE  getContainerHandle() { return INVALID_HANDLE_VALUE; }
    virtual __int64 _m74 (char * pszName) { return 0LL; };
    virtual void    _m78 () {} 
    virtual int     _m7C (char * pszName) { return 0; };

};

С этим, файловые операции должны стать слегко понятнее.

Но, вообще, после ночи копания в PC-шном стриминге, мое мнение о тех, кто делал PC-шный порт, сделало попытку упать еще ниже (попытка провалилась, потому что падать ниже, уже некуда). Двухкратное (а то и трехкратное) дублирование ресурсов в памяти - это норма. Система хитрых ресурс-менеджеров, которая была предназначена для того, чтобы экономить каждый байт крохотной памяти консоли - выкинута, и вместо нее навернуто что-то монстровое, расходующее память в немерянных количествах.
В общем, предварительная оценка потери ресурсов исключительно на неэффективность PC-шного стриминга/ресурс-менеджмента - ~10%. (Интересно, можно ли их отыграть обратно)

Last edited by listener (11-01-2009 10:11)

Offline

#11 09-01-2009 12:49

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: Ресурсы и структуры GTA IV

Частично отреверсенный american.gxt (все миссии и часть MAIN):
http://public.sannybuilder.com/GTA4/ame … versed.rar

Offline

#12 19-01-2009 17:27

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Продолжая тему RSC.
Все, что было сказано на тему флагов, на самом деле, совсем не так.

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

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

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

Зачем это было сделано: страничный механизм был сделан для того, чтобы убрать потребность в непрерывных блоках большого размера (loadingscreens.wtd в распакованном виде занимает ~40M, что с округлением дает нам 64М. Найти непрерывный кусок такого размера в 256М видеопамяти PS3 может быть очень проблематичным (В отличие от 18-ти кусков по два мегабайта).
Блоков должно быть мало, т.к., при правке каждого указателя делается проход по всем блокам этого ресурса. Отсюда - такой странный метод.

Неприятное следствие: если загрузка ресурса получается очень простой, то с записью не все так гладко. При записи мало просто посчитать размер блока, нужно еще и найти относительно оптимальную раскладку структр по блокам. К счастью, эту задачу нужно решить один раз, после чего, найденный алгоритм будет применим для любых данных, хранящихся в RSC.

Напоследок, немножко исходников: http://public.sannybuilder.com/sources/pgbase.rar
Построение списка блоков, загрузка wtd и проверка на выход структур за границы блоков.

Offline

#13 09-10-2009 06:37

VcSaJen
Registered: 25-08-2006
Posts: 217

Re: Ресурсы и структуры GTA IV

А native-Функции все работают? Наверняка среди них есть NOP и unsupported функции. Есть список всех таких функций?


[small][/small]

Offline

#14 09-10-2009 09:58

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Да, 105 функций не имеют обработчика. (список в аттаче)
У меня скрипт, который помечает natives в базе, автоматически определяет (чтобы не переименовывать сто раз nullsub-заглушку.

Что касается unsupported - это делается диффом между списком всех вызываемых из скриптов функций и полным списком.

А в чем глубинный смысл вопроса?

Offline

#15 09-10-2009 11:19

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Ресурсы и структуры GTA IV

думаю, он делает удобный компилятор...


GIMS developer

Offline

#16 09-10-2009 14:28

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Это было бы хорошо.
вот только вопрос тогда получается... странноватый.
(Если бы это была действительно посленяя оставшаяся проблема - такого вопроса бы не было)

Offline

#17 15-10-2009 04:42

VcSaJen
Registered: 25-08-2006
Posts: 217

Re: Ресурсы и структуры GTA IV

@3Doomer -

думаю, он делает удобный компилятор...

Я? grincrazy:crazy: Ты меня с кем-то перепутал.
@listener -

А в чем глубинный смысл вопроса?

Глубинного смысла нет. Я просто хотел узать, какие функции не работают (Ну для поиковика сделать так, что-бы не искать неработающие функции).

Что касается unsupported - это делается диффом между списком всех вызываемых из скриптов функций и полным списком.

То есть все функции, которые не вызываются из оригинальных скриптов, нерабочие? Или я неправильно понял?


[small][/small]

Offline

#18 15-10-2009 08:35

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Ресурсы и структуры GTA IV

что-то я сомневаюсь в последнем случае...


GIMS developer

Offline

#19 15-10-2009 09:20

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Скажем так: они могут работать, но гарантии никакой.
Скорее всего, просто взяли список опкодов VC/SA, загнали их в natives (я видел список оригинальных имен - они такие же, как имена natives), а потом написали код к тому, что реально использовалось.

Offline

#20 15-10-2009 10:23

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Ресурсы и структуры GTA IV

гораздо логичнее предположить, что Р* сначала реализовали кучу функций в ЕХЕ, а потом уже писали скрипты)))
не думаю, что потом стали бы удалять ненужные куски из кода)


GIMS developer

Offline

#21 15-10-2009 11:43

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

Если "сначала" - это 2001..2003 год, то да, полностью согласен

Offline

#22 15-05-2010 09:05

flashTrash
From: Н.Новгород
Registered: 21-02-2007
Posts: 260
Website

Re: Ресурсы и структуры GTA IV

Я извиняюсь за подъем старой темы, но появился вопрос. Меня интересует, как организована работа экстра деталей транспорта(extra1-9). Как они комбинируются (ведь на разных машинах они появляются в разных вариация) и самый главный вопрос - где и как это всё можно отредактировать?

Offline

#23 15-05-2010 10:09

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

@flashTrash - подробно с этим пока никто не разбирался.
В основном, все хранится в wft (там все меши, колы и часть текстур (системные, типа карт нормалей))
Иерархия сборки компонентов, осталась та же, что и в SA.

полного редактора wft, насколько я знаю, еще не написали.
Самое подробное, что есть по wft - мои шаблоны для 010

Offline

#24 15-05-2010 16:44

flashTrash
From: Н.Новгород
Registered: 21-02-2007
Posts: 260
Website

Re: Ресурсы и структуры GTA IV

Как утверждал автор занозы, он не нашел, где в wtf файле хранятся настройки экстр(ну чтобы они одновременно например появлялись). Наверно опять всё зашито.
GTA 4 меня всё больше разочаровывает в плане модинга:cry:

Offline

#25 17-05-2010 08:33

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: Ресурсы и структуры GTA IV

@flashTrash - появление/одновременность экстр, это больше в коде, чем в моделях.

А что касается моддинга... Так копаться надо, пробовать, писать инструменты. Где был бы моддинг SA, если бы не было sannybuilder?

Offline

Board footer

Powered by FluxBB