You are not logged in.
Немного тряхнул стариной перебрал функцию registerNativeByHash взял за основу CHashtable из базы от listener'a
Получилось несколько сумбурно стихийно, но в целом мне кажется неплохо
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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К кода сгенерилось компилятором автоматически. (Т.е., в оригинале это был список функций с параметрами).
Принцип работы такой хэш-таблицы я вычитал у Дженкинса (как раз, когда алгоритм хэш функции читал). Если я ничего не путаю, это называется "хэш-таблица с лавинным заполнением".
У меня, в относительно свежем исходнике, это выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 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; }; |
А вот маленький кусочек самой регистрации нэйтивов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // 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; //.... |
Сами нэйтивы получаются как-то так (несколько самых мелких для примера):
1 2 3 4 | __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.
Таблица второго типа выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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
1 | 0x9FAC 90 void __thiscall CVehicle__doVehicleLights(CVehicle *this, CMatrix *matrix, unsigned int damageStatus) |
Ощущается old-GTA стиль
1 2 | 0x9063E 0 int __thiscall CHeli__preRender(CHeli *this) 0x4E53F 0 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
Исследовал вот эту процедуру
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 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; } |
1 2 3 4 5 | 0x 872810 ; CCutsceneSection *__cdecl CCutscenes__createLights(float fParam) 0x 872410 ; int __cdecl CCutscenes__getOffset(Vector 4 *vector, int sectionID) 0xC68F 80 ; double __thiscall getFloatParam(void *this, char ?offset, int ?time) 0xC68EA 0 ; Vector 4 *__thiscall getVector(void *_CCutsceneLight, Vector 4 *pResultVector, char ?offset, unsigned int ?time) 0xF26F 84 ; int LightOcclWTDindex |
Тут присутсвуют 2 процедуры
1 2 | getVector getFloat |
которые работают с этим dof.
PS Какой обьект возвращает CAnimManager__getAnimByName? Он есть в базе?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | CCamAnimated struc ; (sizeof=0x1BC) 0x 000 cam CCam 0x 140 fState 1 dd ; 0.0 - 1.0 0x 144 fField_ 144 dd ? 0x 148 virtual_getCurrentCutsceneTime dd 0x14C AnimIndex dd 0x 150 cameraAnimNameHash dd 0x 154 field_ 154 dd 0x 158 field_ 158 dd 0x15C field_15C dd 0x 160 cutsceneOffset Vector 4 0x 170 cameraAnimName db 32 0x 190 WADname db 32 0x1B 0 field_1B 0 db 0x1B 1 field_1B 1 db 0x1B 2 field_1B 2 db 0x1B 3 field_1B 3 db 0x1B 4 fState 2 dd 0x1B 8 field_1B 8 dd |
1 2 3 | CVehicle +0xFD 8 m_pDoorData CVehicle +0xFDC m_nDoorsCount CAutomobile +0x1DC 0 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
Хотел бы спросить, что такое
1 2 | 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