Gratt
Модостроитель
- Регистрация
- 14 Ноя 2014
- Сообщения
- 3.301
- Благодарности
- 4.638
- Баллы
- 625
Русский English
Итак, плавно перебираемся к теме движков и с чем их едят. Вернемся в начало и вспомним 4 директории с интерфейсами. Раскрыв любую, мы увидим всю структуру движка из классов и переменных.
Пример класса
Структура класса
Каждый класс движка в юнионе имеет строгую упорядоченность объявлений:
- Декларатор (например zCLASS_DECLARATION)
- Структуры и перечислители (class, struct, union, enum, typedef)
- Поля (int indexBegin[DIMENSION])
- Методы (void Insert( void* ) zCall( 0x0063B3B0 ))
- Виртуальные методы (virtual void SetVisual( zSTRING const& ) zCall( 0x00637160 ))
- Статические методы (static int ArrayCompare( void const*, void const* ) zCall( 0x0063B1B0 ))
- Статические свойства (static zCBBox3DSorterBase*& s_currentSorter)
Стоит отметить, что последние (а также деклараторы, поскольку они включают в себя статические переменные) определяются ссылочно. Их определения находятся в файлах classDef_VerX.cpp и staticDef_VerX.cpp.
Примечание: каждый класс имеет полностью публичный уровень доступа, мне показалось это наиболее удобным вариантом с точки зрения юзабилити.
Вызовы функций движка
Каждый метод класса определяет инструкцию zCall. Она сообщает плагину, что вызов данной функции должен быть осуществлен по указанному адресу в движке. Существуют три исключения:
- Конструктор класса использует инициализирующую функцию с инструкцией zInit на метод, который вызывает zCall.
- Если не существует конструктора класса по умолчанию - такой конструктор остается без инструкций.
- Чисто виртуальный метод. Он использует инструкцию zPureCall.
Также zCall не используется (но существует) в виртуальных методах, где this определен в движке. При обращении к такому методу вызов идет по указателю на vtable и по смещению на конкретную функцию. А если экземпляр создается в плагине, то вызовы таки пойдут через zCall (поскольку создается новый указатель на vtable внутри dll).
Глобальные переменные
Это ряд переменных, использующихся движком на постоянной основе.
Например zCView* screen играет роль вьюпорта, а zCParser* parser отвечает за работу скриптов Gothic.DAT.
Список глобальных переменных можно посмотреть в zGlobal.h каждого движка.
Включение и исключение модулей движка из построения
API движков очень большое, поэтому время на компиляцию может уходить не мало, особенно у кроссплатформенных плагинов. Ускорить сборку можно отключением неиспользуемых модулей движка. Для каждого движка существует файл zEngine.h, где его блоки ограничены директивами #if верхнего уровня. Каждый из блоков может быть отключен конструкцией #if False. Также отключению последуют все блоки зависимые от текущего.
ВАЖНО: При выборе конфигурации проекта под конкретный движок происходит отключение всех блоков, не относящихся к выбранному движку. То есть если выставлена конфигурация G2A Release, то останутся активными только блоки Gothic II: NoTR. Рассмотрим это в другой теме.
Таблица внешних символов
Между собой мы называем это просто 'Names' или 'Gothic names'. Сам файл называется engineNames_VerX.hpp. В нем собрана информация о всех именах движка. Он крайне удобен, так как позволяет оперативно найти необходимый символ, адрес или сигнатуру. В дальнейшем будем использовать его для перехвата функций.
So, we smoothly move to the topic of engines. Let's go back to the beginning and recall 4 directories with interfaces. Expanding any, we will see the whole structure of the engine: classes and variables.
Class example
Class structure
Each engine class in the union has a strict ordering of declaration:
- Declarator(for example zCLASS_DECLARATION)
- Structures and enumerators (class, struct, union, enum, typedef)
- Fields(int indexBegin[DIMENSION])
- Methods(void Insert( void* ) zCall( 0x0063B3B0 ))
- Virtual methods (virtual void SetVisual( zSTRING const& ) zCall( 0x00637160 ))
- Static methods (static int ArrayCompare( void const*, void const* ) zCall( 0x0063B1B0 ))
- Static properties (static zCBBox3DSorterBase*& s_currentSorter)
It is worth noting that the latter (as well as declarators, since they include static variables) are defined by reference. Their definitions are in the classDef_VerX.cpp and staticDef_VerX.cpp files.
Note: each class has a fully public access level, it seemed to me the most convenient option in terms of usability.
Engine function calls
Each class method defines a zCall statement. It tells the plugin that the call to this function should be carried out at the specified address in the engine. There are three exceptions:
- he class constructor uses an initialization function with a zInit on the method that calls zCall.
- If there is no default class constructor, such a constructor is left without instructions.
- A purely virtual method. It uses the zPureCall instruction.
Also zCall is not used (but exists) in virtual methods, where this is defined in the engine. When calling such a method, the call goes by the pointer to vtable and by the offset to a specific function. And if the instance is created in the plugin, then the calls will go through zCall (because a new pointer to the vtable is created inside the dll).
Global variables
This is a series of variables used by the engine permanently
For example zCView* screen plays the role of a viewport, and zCParser* parser is responsible for the operations of Gothic.DAT scripts.
A list of global variables can be found in zGlobal.h of each engine.
Inclusion and exclusion of engine modules from building
The engine API is very large, so compilation time can take a lot of time, especially for cross-platform plugins. You can speed up the assembly by disabling unused engine modules. For each engine, there is a zEngine.h file, where its blocks are limited by the #if top-level directives. Each of the blocks can be disabled by the #if False construct. Also, disabling will be followed by all blocks dependent on the current.
IMPORTANT: When choosing a project configuration for a specific engine, all blocks that are not related to the selected engine are disabled. That is, if the G2A Release configuration is set, then only Gothic II: NoTR blocks will remain active. We will consider this in another topic.
External symbols table
We call it simply 'Names' or 'Gothic names'. The file itself is called engineNames_VerX.hpp.t contains information about all the names of the engine. It is extremely convenient, as it allows you to quickly find the desired character, address or signature. In the future, we will use it to hook functions.
Последнее редактирование модератором: