Как вы узнаете, какие функции вам нужно подключить?
Если говорить прямо, вы должны быть опытным программистом DirectX, чтобы это выяснить. Не ожидайте, что сможете подключиться к структуре, которую вы не понимаете. Так уж получилось, что EndScene
всегда будет вызываться после всех других вызовов отрисовки на цели рендеринга.
Существует множество доступных ресурсов программирования D3D9, в режиме онлайн и в бумажном виде. Большинство из них не бесплатны. Боюсь, что это не тот ответ, на который вы надеялись.
Какое дело с сканированием по шаблону или созданием временного устройства D3D9?
Microsoft этого не сделала приложите любые явные усилия к тому, чтобы сделать EndScene
подключаемым. Просто оказывается подключаемым , потому что каждая нормальная функция подключаема. Вам нужен способ найти функцию в памяти, потому что функция не всегда будет иметь один и тот же адрес.
Один из подходов состоит в поиске известных инструкций, которые появляются внутри функции. Кто-то должен быть первым, кто обнаружит шаблон, который вы можете сканировать. Вы далеко не первый человек, который перехватывает EndScene
, поэтому многие из них ранее перепроектировали функцию и поделились шаблонами для поиска.
ПРИМЕЧАНИЕ. Шаблон не обязательно должен находиться непосредственно внутри целевой функции. Это может также привести вас сначала к чему-то другому, в вашем случае, к экземпляру ID3D9Device
. Важно то, что вы можете каким-то образом найти путь к функции EndScene
.
Другой подход - получить указатель на функцию. Если бы это была обычная функция C, это было бы легко. Здесь трудно, потому что OOP имеет тенденцию усложнять эти вещи - вам нужно пробиться через различные интерфейсы, чтобы получить правильный vtable.
Оба метода имеют свои преимущества и недостатки - создание устройства D3D9 безопаснее, но также более навязчивым, потому что целевой процесс может не ожидать, что кто-то просто случайным образом создаст новые устройства.
Зачем нужна функция подключения __stdcall
?
Поскольку вы замените исходную функцию на вашу перехваченную версию, соглашение о вызове перехваченной функции должно быть таким же, как соглашение о вызове исходной функции. Вызывающая сторона EndScene
ожидает (и была скомпилирована) соглашение __stdcall
, поэтому новая функция также должна вести себя так же, иначе стек будет поврежден. Ваш акт замены функции не меняет способ вызова вызывающего абонента.