Объявления

Друзья, если не получается зарегистрироваться, напишите на почту vdv_forever@bk.ru.
Я оторву свою задницу от всех дел и обязательно Вас активирую! :smile10:
Добро пожаловать на геройский форум! :smile25:

Улучшение ИИ

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 07 май 2020, 20:43

Да, и add esp, ... для __cdecl, а не __stdcall :smile1:
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

Re: Улучшение ИИ

Сообщение Ben80 » 07 май 2020, 20:44

Ну а Роузовский совет то всегда будет работать ? &myDouble будет в 4 байта укладываться ?
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 07 май 2020, 20:44

Цитата:
Примеров я бы кучу привел. Да только давно уже не связываюсь с этим - не пытаюсь менять что-либо в [ebp - N], [ebp + N].

В самом начале темы про плагины, вроде бы, были примеры.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 07 май 2020, 20:46

Цитата:
Ну а Роузовский совет то всегда будет работать ? &myDouble будет в 4 байта укладываться ?

Не знаю, что он имел в виду. Double по частям можно засунуть в два dword'а, а в 4 байта - никак. Только сослаться можно 4-байтовым указателем.
Последний раз редактировалось AlexSpl 07 май 2020, 20:47, всего редактировалось 1 раз.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

Re: Улучшение ИИ

Сообщение Ben80 » 07 май 2020, 20:47

Он имел в виду адрес для Double. А адрес вполне может уложиться в 4 байта.
Вот только всегда ли ? Для экзешника мы видим что адреса 4-байтные, правда, один байт - нули. А для Дллки насколько помню, значащих цифр больше, но, возможно, тоже в 4 байта укладываются.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 07 май 2020, 20:52

Цитата:
Для экзешника мы видим что адреса 4-байтные, правда, один байт - нули.

Это не два адреса, а одно 8-байтное число double, похожее на 1.0, если мы про одно и то же :smile1:

Так, понял. Для dll всё то же самое. Нули в 64-х разрядных приложениях. В 32-х разрядных адреса от 0 до 0x7FFFFFFF (для пользовательского режима; выше - уже ядро).
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 07 май 2020, 21:34

Вот, нашёл в теме про плагины (пример из Орлоглаза):

Код: Выделить всё
int __stdcall captionFix(LoHook* h, HookContext* c)
{
   *(int*)(c->ebp - 0x14) = captionAddr;
   return EXEC_DEFAULT;
}

Здесь мы меняем значение локальной переменной var_14.

Там же про float (но работало бы и с double):

Код: Выделить всё
// Меняем коэффициенты
float eagleEyeCoefs[] = { 0.00f, 0.30f, 0.35f, 0.40f };

_PI->WriteDword(0x63EA2C, (int&)eagleEyeCoefs[1]);
_PI->WriteDword(0x63EA30, (int&)eagleEyeCoefs[2]);
_PI->WriteDword(0x63EA34, (int&)eagleEyeCoefs[3]);
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

Re: Улучшение ИИ

Сообщение RoseKavalier » 07 май 2020, 23:32

AFAIK, pointers in X86 are always 4 bytes wide.
My suggestion was indeed to direct the code to your double by address. It's different than overwriting the actual value as was done for Eagle Eye, but gives you more flexibility.

Код: Выделить всё
constexpr double myDouble = 1.0;
pi->WriteDword(0x4A74A0 + 2, reinterpret_cast<DWORD>(&myDouble));


Изображение

I've changed a lot of variables on the stack using patcher_x86, even adding this to HookContext to make it direct.
Referring to unassigned stack addresses as in your example *should* not result in a crash, Patcher's LoHook even does this to recover ESP...
Изображение
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 07 май 2020, 23:54

Wouldn't it be easier just to compare?

Код: Выделить всё
if (*(double*)(c->ebp + 0xC) < 1.0) { ... }

Provided [ebp + 0xC] is double.

Or

Код: Выделить всё
if (*(float*)(c->ebp + 0xC) < 1.0) { ... }

for float.

Anyway in both cases we compare long doubles.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 08 май 2020, 01:08

Ещё интересна тема точности чисел с плавающей точкой: float (32 бита), double (64 бита) и long double (80 бит).

Например, в следующем листинге при наведении курсора на любое число с плавающей точкой получаем подсказку о том, что это long double:

Код: Выделить всё
if ( a3 < 7.0 )
{
   if ( a3 < 1.0 )
   {
     if ( a3 <= 0.5 )
     {
      LOWORD(v14) = -2;
      if ( a3 <= 0.333 )
        LOWORD(v14) = -3;
     }
     else
     {
      LOWORD(v14) = -1;
     }
   }
   else
   {
     v14 = (signed __int64)(a3 + a3 - 2.0);
   }
}
else
{
   LOWORD(v14) = 11;
}

Хотя, как мы знаем, вещественный литерал без суффикса по умолчанию есть double (например, 7.0 = 7.0 double). Понятно, что и float, и double, и long double попадают в регистры FPU с расширением до long double. Но 1.0f != 1.0 != 1.0l* (в условии равны, а вот в памяти нет). Вот интересный пример:

Код: Выделить всё
As other said, one literal is of type float and the other is of type double. Here is an example where it makes a difference:

#include <stdio.h>

int main(void)
{
    int a = 16777217 * 1.0f;
    int b = 16777217 * 1.0;

    printf("%d %d\n", a, b);
}

prints on my machine:

16777216 16777217

Как бы обычно за точностью мы не гонимся особо. Но в Героях есть алгоритмы, где точность вещественных чисел может сделать разницу (например, в алгоритме определения штрафов за стрельбу через крепостные стены).
Поэтому вопрос: правильно ли писать в листинге декомпиляции a3 + a3 - 2.0 здесь (4A74AD):

Код: Выделить всё
fld dword ptr [ebp+0Ch]
fadd st, st
fsub ds:flt_0063B9E0; это 2.0f

или нужно a3 + a3 - 2.0f? Всё-таки есть же разница, какую 2 отнимать, 2.0 или 2.0f?

* * *
* Хотя с 1.0f неудачный пример.
Проверил, 1.0f загружается как 1.0 в ST0, а вот 1.1f уже как 1.1000000238418579102. И в коде 1.1f == 1.1 - false.
1.1 (double) загружается в ST0 как 1.1000000000000000888, но в коде почему-то 1.1 == 1.1l - уже true.

* * *
Вот, млин, sizeof(long double) == 8 :smile1: Почему?

https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=vs-2019
Короче, Bytes, Range of Values - same as double.

Цитата:
For modern compilers on x64, Clang and GCC uses 16-byte double for long double while VC++ uses 8-byte double. In other words, with Clang and GCC you get higher precision double but for VC++ long double is same as double. The modern x86 CPUs do support these 16-byte doubles so I think Clang and GCC are doing the right thing and allows you to access lower level hardware capability using higher level language primitives.

А когда-то в Паскале был такой тип как Extended... Целых 10 байт! До сих пор думал, что long double есть аналог Extended, а тут такой облом.
Вернуться к началу

Пред.След.

Вернуться в Общий раздел

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1