![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
![]()
Сообщение
#81
|
|
![]() God Сообщений: 267 Спасибо сказали: 25 раз ![]() |
Вот блин. Я понимаю что ответы на вопросы даны. Но я не знаю что с ними делать...
К примеру как ф-ии менять. Там же 16и ричный код. Т.е. как выглядит цифра - понятно. 8 символов. Массив значений умения - 4 по 8. А как ф-я выглядит. И как её менять - не понимаю. К примеру в ф-ии либы как сделать проверку на наличие/уровень навыка дипломатии. То же самое с замедлением. Вижу код. А куда его притулить. И зачем точки остановки нужны не ясно. Мне ж не выйти из ф-ии надо, а изменить её PS: т.е. хочу решение не для конкретно замедления найти, а в целом понять логику. Что бы любую магию/постройку мог менять. Как по примеру с цепочкой городов. Для всех драконов убрал ГМ2 из требований ибо логика смены мне ясна Вот такое же хочу понять для магии. А замедление или "неудача", как пример на котором хочу проследить логику |
|
|
![]()
Сообщение
#82
|
|
![]() Immortal Сообщений: 589 Спасибо сказали: 891 раз ![]() |
Вот блин. Я понимаю что ответы на вопросы даны. Но я не знаю что с ними делать... PS: т.е. хочу решение не для конкретно замедления найти, а в целом понять логику. Что бы любую магию/постройку мог менять. Как по примеру с цепочкой городов. Для всех драконов убрал ГМ2 из требований ибо логика смены мне ясна Было бы все так просто. Универсальных способов нет. Каждую функцию приходится разбирать в коде и придумывать к ней велосипед. К примеру в ф-ии либы как сделать проверку на наличие/уровень навыка дипломатии. Код int __stdcall libraryVisit(LoHook* h, HookContext* c) { // в данном случае esi хранит адрес структуры героя // откуда мы можем найти и дипломатию ( +201 это смещение до втор.навыков / +4 это смещение до дипломатии ) // и выйти на прибавку к первичным параметрам ( +1142 это атака и т.д. ) if (*(char*)(c->esi + 201 + 4) > 1) { // проверка на продвинутую и выше дипломатию char bonnus = (*(char*)(c->esi + 201 + 4)) - 1; // уровень дипломатии -1 чтобы получить правильную прибавку *(char*)(c->esi + 1142) += bonnus; // прибавка к атаке *(char*)(c->esi + 1143) += bonnus; // прибавка к защите *(char*)(c->esi + 1144) += bonnus; // прибавка к колд.силе *(char*)(c->esi + 1145) += bonnus; // прибавка к знаниям } return EXEC_DEFAULT; // после завершения хука выполняется затертый хуком код } Код _PI->WriteLoHook(0x4A2F92, (void*)libraryVisit); // низкоуровневый хук посещения библиотеки с дипломатией То же самое с замедлением. Вижу код. А куда его притулить. И зачем точки остановки нужны не ясно. Мне ж не выйти из ф-ии надо, а изменить её. Вот такое же хочу понять для магии. А замедление или "неудача", как пример на котором хочу проследить логику Код #include <cmath> // для функции округления floor(value + 0.5) int __stdcall new_SlowMul(LoHook* h, HookContext* c) { // тут структура монстра лежит в ecx. // откуда мы и можем получить все интересующие нас параметры float speed = (float)(*(int*)(c->ecx +196)); // получаем скорость монстра (структура +196) c->eax = floor( (speed * (*(float*)(c->ecx + 1224))) + 0.5 ); // функция правильного округления (скорость * коэфф.замедления) // а также приходится "обойти" часть оригинального кода c->return_address = 0x448A37; // указываем новый адрес возврата return NO_EXEC_DEFAULT; // после завершения хука не выполняется затертый хуком код } Код _PI->WriteLoHook(0x448A1A, (void*)new_SlowMul); // хук (замена оригинального куска функции расчета скорости) C магией потом покажу. -------------------- |
|
|
![]()
Сообщение
#83
|
|
![]() God Сообщений: 267 Спасибо сказали: 25 раз ![]() |
В обоих функах получаю ошибку:
Цитата 1>.\dllmain.cpp(275) : error C2664: 'PatcherInstance::WriteLoHook' : cannot convert parameter 2 from 'void *' to '_LoHookFunc_' 1> Conversion from 'void*' to pointer to non-'void' requires an explicit cast Гугланул. Пишут что разные компиляторы, для С/С++. Мол валидный код для С это может быть. Переключил компилятор на С - ошибки синтаксиса... Пробовал контент ифа убрать. Или замедление просто интом сделать. Всё равно та же ошибка Заменив _PI->WriteLoHook(0x4A2F92, (void*)libraryVisit); На _PI->WriteLoHook(0x4A2F92, libraryVisit); Завелось. Но мб я лишнее убрал? PS: проверил. Замедление работае корректно! Спасибо ![]() PPS: Либа работает тоже! |
|
|
![]()
Сообщение
#84
|
|
![]() Immortal Сообщений: 589 Спасибо сказали: 891 раз ![]() |
На счет void* - я не знаю. Баря знает, Сав и Феанор. Они программисты, а я так ... любитель. И Си узнал и использую ток в героях, хотя тут больше заслуга ERMa.
Для данной темы я использую С++ на студио 2008 + инклуд патчера. И да, я обычно проверяю то что выкладываю. Поэтому и посещение библиотеки и округление скорости работают. Но для таких патчей обязательно нужна проверка на !мультиплеер. -------------------- |
|
|
![]()
Сообщение
#85
|
|
![]() laughed as one fey Сообщений: 12 167 Спасибо сказали: 20603 раза ![]() |
Если что-то gcc-based, то там могут быть зловещие чудеса с сложным синтаксисом, да.
(точнее, это у студии зловещие чудеса, а гцц просто менее к ним терпим) |
|
|
![]()
Сообщение
#86
|
|
![]() God Сообщений: 267 Спасибо сказали: 25 раз ![]() |
Попытался найти либу в idb файле. знаю адрес - 0x4A2F92. Но там вообще что попало. Никакого упоминания библиотеки. при этом ф-й которые содержат слово "library" уйма. В чём секрет?)
Вот к примеру для скорости есть такая функа "combatMonster_GetSpeed". Как по ней найти смещение? Знаю что искать надо 196, но ничего похожего не нашел Туда же... Решил проверить на других эл-тах. Нашел метод "getMoraleBonus", как понять его смещение? ЗЫ: Вроде чёт нашел... Код int __stdcall changeMorale(LoHook* h, HookContext* c) { float morale = (float)(*(int*)(c->ecx +114)); c->eax = 2; return NO_EXEC_DEFAULT; } Код _PI->WriteLoHook(0x4E3C3C, changeMorale); Делает мораль = 2 всегда. В виде "временного бонуса" Нашел его так: в одном из мест вызывается "call GetMoralBonus" Глянул там такая строка: mov ecx, Hero ; jumptable 004DB915 case 114 Предположил что 114 это сдвиг. Вроде завелось. Но могу предположить что на другой адрес надо ссылаться, если вешать минус мораль заклинанием. Но так хоть что-то нашел, что отработало) В память об этом сделаю при посещении либы с дипломатией +1/2/3 морали, до след. битвы ![]() |
|
|
![]()
Сообщение
#87
|
|
Immortal Сообщений: 798 Спасибо сказали: 555 раз ![]() |
Многие вопросы отпадают естественным образом, когда начинаешь разбираться, желательно с желанием
![]() Цитата Глянул там такая строка: mov ecx, Hero ; jumptable 004DB915 case 114 Естественно, это не оффсет. Это switch. Таблица как раз таки по адресу 004DB915 и расположена. Нет универсальных решений. Поставьте брейкпоинт на входе известной Вам функции. Пройдите инструкции пошагово, обращая внимание на состояние регистров CPU, FPU, флаги и т.п. Попытайтесь разобраться, как она работает. Это же интересно ![]() |
|
|
![]()
Сообщение
#88
|
|
![]() laughed as one fey Сообщений: 12 167 Спасибо сказали: 20603 раза ![]() |
Мне в реверсинге помогли:
1. Вузовский семестр архитектуры ЭВМ (т.е. х86 ассемблера). 2. Выцыганенная по случаю книжка В.Пирогова "Ассемблер и дизассемблирование". Не говорю, что она лучшая, но она неплоха и была доступна в бумаге. Сейчас есть на флибусте, точн. 3. Четыре года опыта по моддингу мобильников с применением реверс-инженеринга. |
|
|
![]()
Сообщение
#89
|
|
![]() God Сообщений: 267 Спасибо сказали: 25 раз ![]() |
Многие вопросы отпадают естественным образом, когда начинаешь разбираться, желательно с желанием ![]() Цитата Глянул там такая строка: mov ecx, Hero ; jumptable 004DB915 case 114 Естественно, это не оффсет. Это switch. Таблица как раз таки по адресу 004DB915 и расположена. Нет универсальных решений. Поставьте брейкпоинт на входе известной Вам функции. Пройдите инструкции пошагово, обращая внимание на состояние регистров CPU, FPU, флаги и т.п. Попытайтесь разобраться, как она работает. Это же интересно ![]() если это не оффсет, то я случайно угадал что сдвиг у бонуса морали 114?) Ну вот опять спрашиваю - что такое брекпоинты (точки остановки), как их отслеживать, ставить... Как я себе это вижу. Ставлю точку остановки на какой-то участок кода. Когда туда попадаем, я вижу все параметры какие у нас есть. И могу построчно пройти дальше Но проблема в том, что я не код свой запускаю, а скомпилиную ДЛЛку. Выходит точки остановки нужно ставить в ДЛЛке... И да. Игрик говорил что сделать что бы не ругалось на недостающие файлы. Я сразу не обратил внимание, но сейчас вижу что стабильно ругается В самом верху прописано: #include "..\..\patcher_x86.hpp" Патчер на 2 уровня выше и лежит. Пробовал копировать в папку где h и hpp файлы лежат - не помогло |
|
|
![]()
Сообщение
#90
|
|
Immortal Сообщений: 798 Спасибо сказали: 555 раз ![]() |
Запись "case 114" предполагает наличие jumptable ("таблицы переходов"). Например, jumptable может выглядеть так:
dd 00402EA7h, 00402F15h, ..., 0DEADFADEh, ..., 00402F69h Такая jumptable соответствует следующему псевдокоду высокого уровня: switch ( Value ) { case {A}: goto 0x402EA7; case {B}: goto 0x402F15; ... case {X}: goto 0xDEADFADE; ![]() ... default: goto 0x402F69; } , где {A}, {B}, {X} есть некоторые подмножества значений, которые может принимать Value. * * * Обычно в коде встречается что-то вроде этого: Код 00402E8F cmp ecx, 1Ch; switch 29 cases 00402E92 ja loc_402F69; jumptable 00402EA0 default case 00402E98 xor edx, edx 00402E9A mov dl, ds:byte_402FE8[ecx] 00402EA0 jmp ds:off_402FDC[edx*4]; switch jump Здесь следующей после switch джампа jmp ds:off_402FDC[edx*4] будет выполнена инструкция по адресу из jumptable. 402FDCh есть адрес, по которому хранится jumptable, а значение регистра edx выступает в качестве индекса в этой таблице. Индекс находится из таблицы типа такой (см. инструкцию mov dl, ds:byte_402FE8[ecx]): Код 402FE8 (29 cases): db 0, 0, 0, 0 db 0, 2, 2, 2 db 2, 2, 2, 2 db 2, 2, 2, 2 db 2, 1, 1, 1 db 1, 1, 2, 2 db 0, 0, 0, 0 db 0 Т.е. управление передаётся по адресу с соответствующим индексом: Код 402FDC: switch (byte ptr [402FE8h]) { case 0: dd offset loc_402EA7; case 1: dd offset loc_402F15; case 2: dd offset loc_402F69; } И jmp ds:off_402FDC[edx*4] превращается в: jmp loc_402EA7 при edx = 0 (case 0); jmp loc_402F15 при edx = 1 (case 1); jmp loc_402F69 при edx = 2 (case 2, он же default). Инструкции, на которые указывают такие джампы, комментируются в IDA следующим образом: "jumptable {адрес джампа} case {индекс}. |
|
|
![]()
Сообщение
#91
|
|
![]() God Сообщений: 267 Спасибо сказали: 25 раз ![]() |
Индекс находится из таблицы типа такой (см. инструкцию mov dl, ds:byte_402FE8[ecx]): Код 402FE8 (29 cases): db 0, 0, 0, 0 db 0, 2, 2, 2 db 2, 2, 2, 2 db 2, 2, 2, 2 db 2, 1, 1, 1 db 1, 1, 2, 2 db 0, 0, 0, 0 db 0 Код 402FDC: switch (byte ptr [402FE8h]) { case 0: dd offset loc_402EA7; case 1: dd offset loc_402F15; case 2: dd offset loc_402F69; } И jmp ds:off_402FDC[edx*4] превращается в: jmp loc_402EA7 при edx = 0 (case 0); jmp loc_402F15 при edx = 1 (case 1); jmp loc_402F69 при edx = 2 (case 2, он же default). Инструкции, на которые указывают такие джампы, комментируются в IDA следующим образом: "jumptable {адрес джампа} case {индекс}. В данном примере, комментарий такой: "jumptable 00402EA0 cases 5-16,22,23" Значить будут пройдены все кейсы с 5 по 16 и 22 и 23? Но всё равно не ясно: "] Код .text:00402FE8 byte_00402FE8 db 0, 0, 0, 0 ; DATA XREF: MouseClick_AdvMap+2Ar .text:00402FE8 db 0, 2, 2, 2 ; indirect table for switch statement .text:00402FE8 db 2, 2, 2, 2 .text:00402FE8 db 2, 2, 2, 2 .text:00402FE8 db 2, 1, 1, 1 .text:00402FE8 db 1, 1, 2, 2 .text:00402FE8 db 0, 0, 0, 0 .text:00402FE8 db 0 .text:00403005 align 10h далее видим - jmp ds:off_00402FDC[edx*4] Соотв взять 4й или 5й кейс. Если с 0 отсчёт. В данной таблице значение = 0 хоть для 4 хоть для 5. Далее видим следующее: Код .text:00402FDC off_00402FDC dd offset b402FDC_case15_19_39_43 ; DATA XREF: MouseClick_AdvMap+30r .text:00402FDC dd offset b402FDC_case32_36 ; jump table for switch statement .text:00402FDC dd offset b402FDC_caseOther У нас кейс = 0. Значит берём 1й, т.е. b402FDC_case15_19_39_43. Но мне кажется тут у нас уже не кейсы... Или попадаем в caseOther. т.к. для 0 нет кейса. Но всё равно не ясно как для 0 тогада он выглядил бы (ибо сейчас подгоняю под результат скорее) Код .text:00402F69; --------------------------------------------------------------------------- .text:00402F69 .text:00402F69 b402FDC_caseOther: ; CODE XREF: MouseClick_AdvMap+22j .text:00402F69 ; MouseClick_AdvMap+30j .text:00402F69 ; DATA XREF: ... .text:00402F69 push eax ; default .text:00402F69 ; jumptable 00402EA0 cases 5-16,22,23 .text:00402F6A mov ecx, esi .text:00402F6C call ParseMouseClickItem_AdvMap ; Call Procedure .text:00402F71 test eax, eax ; Logical Compare .text:00402F73 jge short loc_00402F80 ; Jump if Greater or Equal (SF=OF) .text:00402F75 pop edi .text:00402F76 pop esi .text:00402F77 xor al, al ; Logical Exclusive OR .text:00402F79 pop ebx .text:00402F7A mov esp, ebp .text:00402F7C pop ebp .text:00402F7D retn 4 ; Return Near from Procedure .text:00402F80; --------------------------------------------------------------------------- Тут джамп тейбл с нужными нам кейсами. Но что дальше происходит - не ясно, кроме как возврат 4ки |
|
|
![]()
Сообщение
#92
|
|
Immortal Сообщений: 798 Спасибо сказали: 555 раз ![]() |
Сложно как-то прокомментировать написанное выше.
Цитата Но что дальше происходит - не ясно, кроме как возврат 4ки Это не возврат 4-ки ![]() Например, Код push edi .text:004089B5 call sub_402E70 .text:004089BA test al, al Здесь функции sub_402E70 передаётся аргумент через стек (edi, 4 байта). Иструкция call sub_402E70 помещает в стек адрес возврата (в данном случае 4089BAh) и передаёт управление по адресу 402E70h. retn 4, соответственно, выталкивает адрес возврата и аргумент из стека и передаёт управление по адресу возврата (инструкция test al, al). |
|
|
![]()
Сообщение
#93
|
|
![]() God Сообщений: 267 Спасибо сказали: 25 раз ![]() |
Пока что ещё запутано как-то выглядит)
Лано, вопрос конкретный появился. Не могу сделать +1/2/3 морали для след. битвы после посещения либы с дипломатией. Точнее просто если есть дипломатия - сделать +2 морали. Цифры сам подправлю Сделать постоянно +2 - выше показал как. (но только при return NO_EXEC_DEFAULT; с вызовом дефолтного метода, не работает +2) А вот после посещения - не получается... делал так, 2 варианта: это всегда есть Код int __stdcall changeMorale(LoHook* h, HookContext* c) { c->eax += 2; return EXEC_DEFAULT; } Код _PI->WriteLoHook(0x4A2F92, libraryVisit); 1. libraryVisit code: Код int __stdcall libraryVisit(LoHook* h, HookContext* c) { /// library code here *(int*)0x4E3C3C = (int)changeMorale; } return EXEC_DEFAULT; } 2. libraryVisit code: Код int __stdcall libraryVisit(LoHook* h, HookContext* c) { /// library code here _P = GetPatcher(); _PI = _P->GetInstance("HD.Plugin.DedMorozzz"); _PI->WriteLoHook(0x4E3C3C, changeMorale); } return EXEC_DEFAULT; } Игра вылетает при любом раскладе, после посещения/открытия окна героя Как сделать временный бонус к морали? |
|
|
![]()
Сообщение
#94
|
|
Immortal Сообщений: 798 Спасибо сказали: 555 раз ![]() |
Значение морали не может быть больше +3 или меньше -3.
Я не знаю, корректен ли код выше вообще, но это Код c->eax += 2; точно неправильно. |
|
|
![]()
Сообщение
#95
|
|
![]() God Сообщений: 267 Спасибо сказали: 25 раз ![]() |
не в этом дело. Герой которым посещая либу с нулевой моралью..
Да и "рабочий" вариант, всегда +2 морали делает +5 у героя в сумме(в бою ещё больше). Просто учитывается только 3. Банальный пример. Эксперт лидерство и архангел. Уже больше 3х. Просто в бою не важно +3 или +15 морали В чём у меня ошибка. Как задать +2 морали при посещении либы? |
|
|
![]()
Сообщение
#96
|
|
Immortal Сообщений: 798 Спасибо сказали: 555 раз ![]() |
Насколько я помню, бонусы морали хранятся отдельно от значения морали в структуре героя. И есть функция (типа GetMorale), которая каждый раз считает мораль (проходит по артам, бонусам от объектов).
|
|
|
![]()
Сообщение
#97
|
|
Immortal Сообщений: 798 Спасибо сказали: 555 раз ![]() |
Костыль, или решение в лоб. Т.к. бонус морали от посещения Библиотеки предполагается сделать временным, то этот бонус можно добавить к бонусу за посещение Фонтана Молодости, например. Коду, который обнуляет временные бонусы, пофиг.
P.S. Это в случае, если подобные бонусы не хранятся в битовом поле. Нужен, как минимум байт, чтобы работало. Ну и, естественно, по правому клику не увидишь, что была посещена именно Библиотека. |
|
|
![]()
Сообщение
#98
|
|
![]() Immortal Сообщений: 589 Спасибо сказали: 891 раз ![]() |
Лано, вопрос конкретный появился. Не могу сделать +1/2/3 морали для след. битвы после посещения либы с дипломатией. Точнее просто если есть дипломатия - сделать +2 морали. Цифры сам подправлю Как сделать временный бонус к морали? Просто добавь в ту функцию хука в библиотеке Код *(char*)(c->esi + 1145) += bonnus; // прибавка к знаниям *(char*)(c->esi + 282) += 2; // +2 временно до следующей битвы upd: упсс, подправил *(int*) y на *(char*). -------------------- |
|
|
![]()
Сообщение
#99
|
|
Immortal Сообщений: 798 Спасибо сказали: 555 раз ![]() |
Цитата Код *(int*)(c->esi + 282) += 2; // +2 временно до следующей битвы Прокомментируйте, пожалуйста. +2 к чему добавляется? |
|
|
![]()
Сообщение
#100
|
|
![]() Immortal Сообщений: 589 Спасибо сказали: 891 раз ![]() |
-------------------- |
|
|
![]() ![]() |
Текстовая версия | Сейчас: 28 September 2025 - 03:24 |
Copyright by Алексей Крючков
![]() Programming by Degtyarev Dmitry |
|