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