Объявления

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

Как создать плагин для HD мода

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 19 фев 2019, 17:42

Ben80 писал(а):

А вот если бы попробовали мое предложение, скорее всего, не пришлось бы менять код.


Попробовал ваш код, к сожалению, после обновления HD мода он тоже не работает.
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 20 фев 2019, 10:18

as239 писал(а):

Ben80 писал(а):

А вот если бы попробовали мое предложение, скорее всего, не пришлось бы менять код.


Попробовал ваш код, к сожалению, после обновления HD мода он тоже не работает.


Переделал код так и он заработал:

Код: Выделить всё
   int DllPatchAddress = 0;
   int approxDllSize = 0x2557D;
   HMODULE hHW_SOD = GetModuleHandleA("HW_SOD.dll");

   for(int i=0; i<approxDllSize; i++)
   {
      if(*(int*)((int)hHW_SOD + i) == 0xFFFFFFFFC085D0FF) DllPatchAddress = (int)hHW_SOD + i + 4;

   }

   if (DllPatchAddress != 0 && hHW_SOD ) _PI->WriteByte( DllPatchAddress, 0xEB);

    return EXEC_DEFAULT;


Насколько это надежный вариант? Правильно ли я выбрал последовательность байт для проверки?

ИЗМ: А если сделать прерывание цикла, то не работает, почему?
Код: Выделить всё
      if(*(int*)((int)hHW_SOD + i) == 0xFFFFFFFFC085D0FF) {
         DllPatchAddress = (int)hHW_SOD + i + 4;
         break;
      }

Кажется понял, это последовательность еще где-то встречается, но последняя нужная.

Во вложении плагин, если кто-то еще может, проверьте, пожалуйста, работает ли перестройка ГМ с первого уровня.
Вложения
FreshMod.zip
(6.39 КБ) Скачиваний: 259
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение Ben80 » 20 фев 2019, 13:46

as239 писал(а):

Насколько это надежный вариант? Правильно ли я выбрал последовательность байт для проверки?


Не знаю, правильно ли. Было бы полезно для вас, если бы вы точно ответили на вопрос, почему мой код не сработал - потому ли, что сигнатура изменилась, чего опасался AlexSpl, либо потому что я просто где-то допустил грубую ошибку.

То, что с брейком не работает, возможно, указывает на то, что такая сигнатура встречается несколько раз, при этом нужной оказывается конкретно последняя такая сигнатура.

Насчет approxDllSize - в коде RoseKavalier, показано как опереровать точным размером Dll,а не как у меня. Конечно, это гораздо правильнее.
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 20 фев 2019, 13:53

Ben80 писал(а):

as239 писал(а):

Насколько это надежный вариант? Правильно ли я выбрал последовательность байт для проверки?


Не знаю, правильно ли. Было бы полезно для вас, если бы вы точно ответили на вопрос, почему мой код не сработал - потому ли, что сигнатура изменилась, чего опасался AlexSpl, либо потому что я просто где-то допустил грубую ошибку.

То, что с брейком не работает, возможно, указывает на то, что такая сигнатура встречается несколько раз, при этом нужной оказывается конкретно последняя такая сигнатура.

Насчет approxDllSize - в коде RoseKavalier, показано как опереровать точным размером Dll,а не как у меня. Конечно, это гораздо правильнее.


Да сигнатура изменилась, у нас совпадают только 4 байта, вот рабочий код на текущей версии HD-мода:

Код: Выделить всё
int __stdcall patchDll(LoHook* h, HookContext* c)
{
   int DllPatchAddress = 0;
   int approxDllSize = 0x2557D;
   HMODULE hHW_SOD = GetModuleHandleA("HW_SOD.dll");

   for(int i=0; i<approxDllSize; i++)
   {
      if(*(int*)((int)hHW_SOD + i) == 0xB850016A)
         if(*(int*)((int)hHW_SOD + i + 4) == 0x4305A0)
            if(*(int*)((int)hHW_SOD + i + 8) == 0xC085D0FF){
               DllPatchAddress = (int)hHW_SOD + i + 12;
               break;
            }
   }

   if (DllPatchAddress != 0 && hHW_SOD ) _PI->WriteByte( DllPatchAddress, 0xEB);

   return EXEC_DEFAULT;
}


От правок похоже никуда не деться, но плюс этого кода в том, что при изменении сигнатуры в HD-моде, изначальная логика перестройки не ломается.
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение Ben80 » 20 фев 2019, 13:57

Было бы интересно узнать, что по этому поводу думает RoseKavalier.
Он, конечно, писал по этому поводу, и даже код давал, но было б здорово, если бы попроще объяснил :smile1:
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 20 фев 2019, 14:01

Никто не знает как в коде igrik по обмену между героями в городе - после выхода из города, опять войти в него, как это делал AlexSpl?

Код igrik:
Код: Выделить всё
int __stdcall Y_DlgTown_Proc(HiHook* hook, _TownMgr_* tm, _EventMsg_* klick)
{
   int res = CALL_2(int, __thiscall, hook->GetDefaultFunc(), tm, klick);

   if (res) {
      if (klick->type == 2 && klick->subtype == HK_E) {
         int heroU_id = tm->town->up_hero_id;
         int heroD_id = tm->town->down_hero_id;

         if ( heroU_id != -1 && heroD_id != -1) {
            _Hero_* heroU = o_GameMgr->GetHero(heroU_id);
            _Hero_* heroD = o_GameMgr->GetHero(heroD_id);

            CALL_2(void, __fastcall, 0x4A25B0, heroU, heroD);// Показываем диалог Грамотности
            CALL_3(void, __thiscall, 0x4AAA60, o_AdvMgr, heroU, heroD);// Показываем диалог встречи героев

            // делаем автоматический выход из окна города
            o_WndMgr->result_dlg_item_id = 0x7800;
            klick->type = 0x4000;
            klick->subtype = 1;
            klick->item_id = 10;

         //CALL_2(int, __thiscall, 0x5C67C0, o_TownMgr, 0);

            return 2;
         }
      }
   }
   return res;
}

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

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

Re: Как создать плагин для HD мода

Сообщение RoseKavalier » 20 фев 2019, 20:37

@AlexSpl
7.0 solved it, thanks for suggestion!

@as239
Hero exchange in town problem was solved, igrik should have working version.

If you need the second needle in a DLL then it may not be the best needle, but this can still be accomplished by setting a condition to find #n match. 4 bytes for a needle needs to be very specific.
Better use a few more bytes, e.g. the one I posted earlier:
Код: Выделить всё
BYTE needle[] = { 0xB8, 0xA0, 0x05, 0x43, 0x00, 0xFF, 0xD0, 0x85, 0xC0, 0x75 };
int offset = 9;


Use memmem to find address directly by passing needle, sizeof(needle) and correct it with offset. Or look in general area for the correct spot to patch.
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 21 фев 2019, 08:49

@RoseKavalier

I'm trying to use your code, but I have 2 problems:
1. How to convert HW_SOD_DLL to unsigned char? ( error C2664: 'memmem' : cannot convert parameter 1 from 'DWORD' to 'unsigned char *' )
2. How to use result of memmem()?

Код: Выделить всё
   DWORD HW_SOD_DLL, HW_SOD_SIZE;
   GetDllInfo("HW_SOD.dll", HW_SOD_DLL, HW_SOD_SIZE); // after HW_SOD is installed, around 0x4F823F

   BYTE needle[] = { 0xB8, 0xA0, 0x05, 0x43, 0x00, 0xFF, 0xD0, 0x85, 0xC0, 0x75 };
   int offset = 9;

   unsigned char HowToUseIt = memmem( HW_SOD_DLL, HW_SOD_SIZE, needle, sizeof(needle) );
   if ( HowToUseIt != NULL ) _PI->WriteByte( Something? + offset, 0xEB);
Вернуться к началу

offlineigrik  
Подмастерье
Подмастерье
 
Сообщения: 108
Зарегистрирован: 14 сен 2017, 12:35
Пол: Не указан
Поблагодарили: 84 раз.

Re: Как создать плагин для HD мода

Сообщение igrik » 21 фев 2019, 09:04

Был огромный завал на работе, поэтому я не отписывался по результату.
Вот упрощенный код обмена героями в замке. Огромное спасибо RoseKavalier, за помощь!

Код: Выделить всё
#define HK_E 18
#define o_Executive (*(int*)0x699550)
bool inTownDlg;

char __stdcall Y_DlgTown_Proc(HiHook* hook, _TownMgr_* tm, _EventMsg_* klick)
{
   char res = CALL_2(char, __thiscall, hook->GetDefaultFunc(), tm, klick);
   inTownDlg = false;

   if (res) {
      if (klick->type == 2 && klick->subtype == HK_E) {
         int heroU_id = tm->town->up_hero_id;
         int heroD_id = tm->town->down_hero_id;

         if ( heroU_id != -1 && heroD_id != -1) {
            _Hero_* heroU = o_GameMgr->GetHero(heroU_id);
            _Hero_* heroD = o_GameMgr->GetHero(heroD_id);

            inTownDlg = true;

            if ( *(int*)((int)o_Executive +4) != (int)o_WndMgr ) {
               *(int*)((int)o_TownMgr +4) = (int)o_AdvMgr;
               *(int*)((int)o_TownMgr +8) = (int)o_WndMgr;

               *(int*)((int)o_AdvMgr +4) = NULL;
               *(int*)((int)o_AdvMgr +8) = (int)o_WndMgr;            

               *(int*)((int)o_WndMgr +4) = (int)o_TownMgr;
               *(int*)((int)o_WndMgr +8) = (int)o_MouseMgr;
            }
            CALL_2(void, __fastcall, 0x4A25B0, heroU, heroD);
            CALL_3(void, __thiscall, 0x4AAA60, o_TownMgr, heroU, heroD);

            CALL_1(void, __thiscall, 0x5D5930, o_TownMgr);       
            CALL_1(void, __thiscall, 0x5D5810, o_TownMgr);   

            inTownDlg = false;

            return 1;   
         }
      }
   }

   return res;
}

int __stdcall Y_Dlg_HeroesMeet(LoHook* h, HookContext* c)
{   
   if ( inTownDlg ) { // пропускаем обновление экрана
      c->return_address = 0x4AAC2A;
      return NO_EXEC_DEFAULT;
   }
   return EXEC_DEFAULT;
}
////////////////////////////////////////////////
_PI->WriteHiHook(0x5D3640, SPLICE_, EXTENDED_, THISCALL_, Y_DlgTown_Proc);
_PI->WriteLoHook(0x4AAC1B, Y_Dlg_HeroesMeet);
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение RoseKavalier » 21 фев 2019, 13:49

as239 писал(а):

@RoseKavalier

I'm trying to use your code, but I have 2 problems:
1. How to convert HW_SOD_DLL to unsigned char? ( error C2664: 'memmem' : cannot convert parameter 1 from 'DWORD' to 'unsigned char *' )
2. How to use result of memmem()?


1. Cast to unsigned char, (unsigned char*)HW_SOD_DLL (or modify GetDllInfo)
2. memmem() gives out the address found (e.x. 0x5472025) or 0 if the needle is not found.

Код: Выделить всё
DWORD HW_SOD_DLL, HW_SOD_SIZE;
GetDllInfo("HW_SOD.dll", HW_SOD_DLL, HW_SOD_SIZE); // after HW_SOD is installed, around 0x4F823F

BYTE needle[] = { 0xB8, 0xA0, 0x05, 0x43, 0x00, 0xFF, 0xD0, 0x85, 0xC0, 0x75 };
int offset = 9;

DWORD address = (DWORD)memmem((unsigned char*)HW_SOD_DLL, HW_SOD_SIZE, needle, sizeof(needle));
if (address)
    _PI->WriteByte(address + offset, 0xEB);


In a few weeks (when things are ready) I will release some code to make this simpler. In old SoD_SP it's kind of a mess like this, new SoD_SP is better!
Вернуться к началу

Пред.След.

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

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

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