You are not logged in.
Немного тряхнул стариной перебрал функцию registerNativeByHash взял за основу CHashtable из базы от listener'a
Получилось несколько сумбурно стихийно, но в целом мне кажется неплохо
struct CHashData
{
int hash;
int addr;
};
struct CHashtable // 0x01865954 in EFLC
{
CHashData *m_pData;
int m_nSize;
int m_nRequestedSize;
int m_nCount;
};
CHashtable Hashtable;
char __stdcall registerNativeByHash(unsigned int a1, int a2)
{
int v2; // edi@1
unsigned int v4; // edx@5
unsigned int v5; // ecx@5
unsigned int v6; // eax@5
v2 = Hashtable.m_nSize;
if ( !Hashtable.m_nSize )
{
sub_4CF3D0();
v2 = Hashtable.m_nSize;
}
if ( Hashtable.m_nCount == v2 )
return 0;
v4 = a1 % v2;
v5 = a1;
v6 = Hashtable.m_pData[a1 % v2].hash;
if ( v6 > 1 )
{
while ( v6 != a1 )
{
v5 = (v5 >> 1) + 1;
v4 = (v5 + v4) % v2;
v6 = Hashtable.m_pData[v4].hash;
if ( v6 <= 1 )
goto LABEL_8;
}
return 0;
}
LABEL_8:
Hashtable.m_pData[v4].hash = a1;
Hashtable.m_pData[v4].addr = a2;
++Hashtable.m_nCount;
return 1;
}
Last edited by VoLT (23-07-2011 21:08)
Offline
Хорошо, только goto немного не к месту.
А вообще, там практически все сделано на template, и, примерно 300К кода сгенерилось компилятором автоматически. (Т.е., в оригинале это был список функций с параметрами).
Принцип работы такой хэш-таблицы я вычитал у Дженкинса (как раз, когда алгоритм хэш функции читал). Если я ничего не путаю, это называется "хэш-таблица с лавинным заполнением".
У меня, в относительно свежем исходнике, это выглядит так:
template <class T> class scrHashtable {
public:
struct Pair {
DWORD dwKey;
T item;
};
__inline T operator[] (const DWORD dwKey) {
if (!m_dwAllocatedSize) return NULL;
DWORD i = dwKey % m_dwAllocatedSize;
DWORD h = dwKey;
while (m_pData[i].dwKey != dwKey) {
if (!m_pData[i].dwKey) return NULL;
h = (h >> 1)+1;
i = (i+h) % m_dwAllocatedSize;
}
return m_pData[i].item;
}
bool insert (DWORD dwKey, T item) {
if (m_dwAllocatedSize == m_dwCount)
return false; // table full
DWORD i = dwKey%m_dwAllocatedSize;
DWORD h = dwKey; // R9
while (m_pData[i].dwKey > 1) {
if (m_pData[i].dwKey == dwKey) {
trace ("FATAL: native $%x is already registered\n", dwKey);
exit (0);
return false; // already present
}
h = (h >> 1)+1;
i = (i+h) % m_dwAllocatedSize;
}
m_pData[i].dwKey = dwKey;
m_pData[i].item = item;
m_dwCount++;
return true;
}
Pair * m_pData;
DWORD m_dwAllocatedSize;
DWORD m_dwInitialSize;
DWORD m_dwCount;
};А вот маленький кусочек самой регистрации нэйтивов:
// Native: no args, no return value
template <DWORD K, void (*F)()> class Native {
public:
Native () { scrVM::ms_natives->insert (K, invoke); }
static void __cdecl invoke (NativeParam&) { F(); }
};
// ....
// Native 2 args, return value
template <DWORD K, typename R, typename A1, typename A2, R (*F)(A1, A2)> class NativeR2{
public:
NativeR2 () { scrVM::ms_natives->insert (K, invoke); }
static void __cdecl invoke (NativeParam& p) { p.pRet[0] = F (p.pArgs[0], p.pArgs[1]); }
};
// ...
void scrVM::registerSystemNatives () {
NativeR <0x75706300, int, TIMERA> _TIMERA;
NativeR <0x62984AB7, int, TIMERB> _TIMERB;
NativeR <0x1BF55D6F, int, TIMERC> _TIMERC;
Native1 <0x32501B1E, int, SETTIMERA> _SETTIMERA;
Native1 <0x3B4C2E2E, int, SETTIMERB> _SETTIMERB;
Native1 <0x499852DB, int, SETTIMERC> _SETTIMERC;
//....Сами нэйтивы получаются как-то так (несколько самых мелких для примера):
__inline int TIMERA () { return scrThread::getRunningThread()->m_context.nTimerA; } // $75706300
__inline void SETTIMERA (int n) { scrThread::getRunningThread ()->m_context.nTimerA = n; } // $32501B1E
__inline DWORD SHIFT_LEFT (DWORD d, DWORD s) { return d << s; } // $102A0A6C
__inline DWORD SHIFT_RIGHT (DWORD d, DWORD s) { return d >> s; }// $64DD173C
Offline
Продолжу тему хэш-таблиц.
IV использует три разных типа хэш-таблиц, с требя разными алгоритмами хэшей.
Первый - приведенный выше, в котором используется Jenkins one at time hash. используется для нэутивов и загруженных скриптов.
Второй - массив связных списков. Хэш-функция - ELF hash. Используется как кэш vertex declaration и в парсерах текстовых форматов.
Третий - балансированное дерево в grcResourceCache. Хэш-функция - CRC32.
Таблица второго типа выглядит так:
template<typename T> class atHashtable {
protected:
struct Entry {
// ... здесь были конструктор и деструктор ...
const char * pszKey; // TODO: use sysString
T item;
Entry * pNext;
};
public:
// ... какое-то количество кода пропущено ...
T* at (const char * pszKey) const {
if (!wSize) return *NULL;
DWORD dwIndex = sysHashElf (pszKey);
while (Entry * p = pItems[dwIndex]; p; p = p->pNext)
if (!strcmp (pszKey, p->pszKey))
return &(p->item);
return NULL;
}
// в отличие от atArray, здесь сначала идет wSize, а потом wCount
Entry** pData; // +0 array of linked lists of Entry
WORD wSize; // +4 allocated size
WORD wCount; // +6 number of used items
WORD _f8;
BYTE _fA;
BYTE bInitialized; // +B
};
Offline
0x1202800 - в базе listener'а (1.0.4) - старт CPickups?
0x8DF0C0 - destroyPickup?
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Ув. listener, будете ли обновлять базу по IV?)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
listener, а что насчёт построения моделей в IV, как например в RW - Clump>Frame>Atomic. Может известны уже какие-то структуры?
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Графические форматы RAGE разобраны процентов на 80 для IV и процентов на 50 для RDR.
(MC:LA - тоже процентов на 50). Просто большого потока интересующихся не было, и информация перестала выходить за пределы "узкого круга"
Offline
listener, спасибо)
Last edited by DK22Pac (08-02-2012 21:45)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Нубский вопро - как получить SkeletonData, если есть CEntity?
Last edited by DK22Pac (09-02-2012 00:00)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Но ведь modelInfo - общий для всех Entity с этой моделью?
Мне нужно для конкретного субьекта найти.
Ещё один вопрос. frag - это материальный компонент? Как rpAtomic?
Last edited by DK22Pac (09-02-2012 01:20)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
0x9FAC90 void __thiscall CVehicle__doVehicleLights(CVehicle *this, CMatrix *matrix, unsigned int damageStatus)
Ощущается old-GTA стиль 
0x9063E0 int __thiscall CHeli__preRender(CHeli *this) 0x4E53F0 int __thiscall CVehicle__getBone(CVehicle *vehicle, int boneID)
PS что-то hex-rays кидает все операции с регистрами xm в __asm{}, может это исправили в новых версиях?
UP
listener, если будет время, пожалуйста, обьясните, что это:
crFrameDofVector3
crFrameDofFloat
Last edited by DK22Pac (18-04-2012 14:19)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Ну и вот некоторые разобранные (почти
) структуры
ссылка
Last edited by DK22Pac (29-04-2012 11:28)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Хорошо. До катсцен я еще не добирался.
Маленькое замечание: размер rage::Vector3 - не 12, а 16 байт (SSE-aligned)
В паре объектов "лишние" четыре байта используется для хранения даных, но, практически везде, это просто выравнивание.
Пропустил вопрос про FrameDof
DOF = Degree Of Freedom
короче, на первый взгляд, это ограничения для инверсной кинематики.
Они у меня были слегка разобраны, если надо - попробую поискать
Offline
listener
Исследовал вот эту процедуру
CCutsceneSection *__cdecl CCutscenes::createLights(int fParam)
{
CCutsceneSection *_pSection; // eax@1
CCutsceneLight *light; // esi@3
int v5; // edi@5
Vector4 *pOffset; // eax@5
Vector4 *vecLightCutsPos; // edx@5
float lightPosY; // xmm0_4@5
float lightPosZ; // xmm1_4@5
float lightPosX; // xmm2_4@5
int pSection; // eax@5
int _section; // eax@5
int flags; // [sp-14h] [bp-B8h]@6
Vector4 *pLightDirection; // [sp-10h] [bp-B4h]@6
Vector4 *pShadowDirection; // [sp-Ch] [bp-B0h]@6
int pLightPos; // [sp-8h] [bp-ACh]@6
int pRGBA; // [sp-4h] [bp-A8h]@6
float _range; // [sp+0h] [bp-A4h]@6
int zero; // [sp+4h] [bp-A0h]@6
int wtd; // [sp+8h] [bp-9Ch]@6
float _intensity1; // [sp+Ch] [bp-98h]@6
float halfIntensity; // [sp+10h] [bp-94h]@6
float _intensity2; // [sp+14h] [bp-90h]@6
int minusOne; // [sp+18h] [bp-8Ch]@6
int _minusOne; // [sp+1Ch] [bp-88h]@6
int pCutsceneLight; // [sp+20h] [bp-84h]@6
float intensity2; // [sp+34h] [bp-70h]@5
float intensity1; // [sp+38h] [bp-6Ch]@5
float range; // [sp+3Ch] [bp-68h]@4
int i; // [sp+40h] [bp-64h]@2
Vector4 shadowDirection; // [sp+44h] [bp-60h]@4
Vector4 lightDirection; // [sp+54h] [bp-50h]@5
Vector4 _lightPos; // [sp+64h] [bp-40h]@5
int RGB; // [sp+74h] [bp-30h]@5
int buf1[4]; // [sp+84h] [bp-20h]@5
int buf2[4]; // [sp+94h] [bp-10h]@5
_pSection = cutsceneSections[_dwCutscenePlayState];
if ( _pSection )
{
i = 0;
if ( _pSection->numLights > 0 )
{
light = 0xF930;
do
{
LODWORD(shadowDirection.x) = 0;
LODWORD(shadowDirection.y) = fOne;
LODWORD(shadowDirection.z) = 0;
range = getFloatParam(*(&_pSection->offset.x + light), 0x8Cu, fParam);
__asm { lahf }
if ( __SETP__(_AH & 0x44, 0) )
{
getVector(*(&light->anim + cutsceneSections[_dwCutscenePlayState]), buf1, 0, fParam);
v5 = _dwCutscenePlayState;
pOffset = CCutscenes__getOffset(buf2, _dwCutscenePlayState);
lightPosY = vecLightCutsPos->y + pOffset->y;
lightPosZ = vecLightCutsPos->z + pOffset->z;
lightPosX = vecLightCutsPos->x + pOffset->x;
pSection = cutsceneSections[v5];
_lightPos.x = lightPosX;
_lightPos.y = lightPosY;
_lightPos.z = lightPosZ;
getVector(*(&light->anim + pSection), &lightDirection, 0x8Fu, fParam);
getVector(*(&light->anim + cutsceneSections[_dwCutscenePlayState]), &RGB, 0x8Bu, fParam);
intensity1 = getFloatParam(*(&light->anim + cutsceneSections[_dwCutscenePlayState]), 0x8Du, fParam);
intensity2 = getFloatParam(*(&light->anim + cutsceneSections[_dwCutscenePlayState]), 0x8Eu, fParam);
_section = cutsceneSections[_dwCutscenePlayState];
shadowDirection.x = lightDirection.y;
shadowDirection.y = lightDirection.z;
LODWORD(shadowDirection.z) = lightDirection.x;
if ( strncmp("shd", &light->name[cutsceneSections[_dwCutscenePlayState]]) )
{
pCutsceneLight = (light + cutsceneSections[_dwCutscenePlayState]);
_minusOne = -1;
minusOne = -1;
_intensity2 = intensity2;
halfIntensity = intensity2 * 0.5;
_intensity1 = intensity1;
wtd = LightOcclWTDindex;
zero = 0;
_range = range;
pRGBA = &RGB;
pLightPos = &_lightPos;
pShadowDirection = &shadowDirection;
pLightDirection = &lightDirection;
flags = 0x184u;
}
else
{
pCutsceneLight = 0;
_minusOne = -1;
minusOne = -1;
_intensity2 = intensity2;
halfIntensity = intensity2 * 0.5;
_intensity1 = intensity1;
if ( strncmp("env", &light->name[_section]) )
{
wtd = LightOcclWTDindex;
zero = 0;
_range = range;
pRGBA = &RGB;
pLightPos = &_lightPos;
pShadowDirection = &shadowDirection;
pLightDirection = &lightDirection;
flags = 0x180u;
}
else
{
wtd = LightOcclWTDindex;
zero = 0;
_range = range;
pRGBA = &RGB;
pLightPos = &_lightPos;
pShadowDirection = &shadowDirection;
pLightDirection = &lightDirection;
flags = 0x80u;
}
}
_registerLight( v5, 0, 2, flags, pLightDirection, pShadowDirection, pLightPos, pRGBA, _range, zero, wtd, _intensity1, halfIntensity, _intensity2, minusOne, _minusOne, pCutsceneLight);
}
_pSection = cutsceneSections[_dwCutscenePlayState];
++light;
++i;
}
while ( i < _pSection->numLights );
}
}
return _pSection;
}0x872810 ; CCutsceneSection *__cdecl CCutscenes__createLights(float fParam) 0x872410 ; int __cdecl CCutscenes__getOffset(Vector4 *vector, int sectionID) 0xC68F80 ; double __thiscall getFloatParam(void *this, char ?offset, int ?time) 0xC68EA0 ; Vector4 *__thiscall getVector(void *_CCutsceneLight, Vector4 *pResultVector, char ?offset, unsigned int ?time) 0xF26F84 ; int LightOcclWTDindex
Тут присутсвуют 2 процедуры
getVector getFloat
которые работают с этим dof.
PS Какой обьект возвращает CAnimManager__getAnimByName? Он есть в базе?
CCamAnimated struc ; (sizeof=0x1BC) 0x000 cam CCam 0x140 fState1 dd ; 0.0 - 1.0 0x144 fField_144 dd ? 0x148 virtual_getCurrentCutsceneTime dd 0x14C AnimIndex dd 0x150 cameraAnimNameHash dd 0x154 field_154 dd 0x158 field_158 dd 0x15C field_15C dd 0x160 cutsceneOffset Vector4 0x170 cameraAnimName db 32 0x190 WADname db 32 0x1B0 field_1B0 db 0x1B1 field_1B1 db 0x1B2 field_1B2 db 0x1B3 field_1B3 db 0x1B4 fState2 dd 0x1B8 field_1B8 dd
CVehicle +0xFD8 m_pDoorData CVehicle +0xFDC m_nDoorsCount CAutomobile +0x1DC0 CAutomobileDoor[6]
Last edited by DK22Pac (04-05-2012 13:36)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Хотел бы спросить, что такое
CBaseDC CBaseDC::Execute
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
@DK22Pac - DC == Display Command.
Т.е., несколько упрощая, по ходу обработки, они набираются в очередь и потом отрисовываются все пачкой. CBaseDC - базовый класс для всех DC, а Execute - метод, непосредственно выполняющий команду.
Offline
В паблике не так давно появилась замечательная база EFLC http://public.sannybuilder.com/gtasa_ex … 141007.rar
А для GTA IV 1.0.7 имеется подобная?
Offline