Объявления | ||
---|---|---|
Друзья, если не получается зарегистрироваться, напишите на почту vdv_forever@bk.ru. Я оторву свою задницу от всех дел и обязательно Вас активирую! Добро пожаловать на геройский форум! |
Re: Heroes2 - вставляем свои аватарыЯ понял Вашу идею. Сделать это будет сложнее, чем просто увеличить атаку. Однако и это возможно, хотя придётся немного потрудиться
|
|
Re: Heroes2 - вставляем свои аватарыМожет надо выбрать другую магию для модификации, не обязательно жажду крови ... * ладно, ушель... надеюсь решим эту задачу как то *
|
|
Re: Heroes2 - вставляем свои аватарыЖажда крови лучше всего с точки зрения анимации подходит. Монстр как бы озверел, аж покраснел весь
Доброе утро |
Re: Heroes2 - вставляем свои аватарыНапишу сегодня часть третью, в которой мы сделаем так, чтобы "Жажда крови" увеличивала урон отряда вместо атаки.
|
|
Re: Heroes2 - вставляем свои аватарыок
сегодня мы им зададим урон вместо атаки) |
|
Re: Heroes2 - вставляем свои аватарыКажися не сегодня) черт
|
Re: Heroes2 - вставляем свои аватарыЧасть третья
В предыдущих двух частях статьи мы нашли участки кода, отвечающие за работу заклинания "Жажда крови", а именно: код, увеличивающий значение атаки отряда на 3 ед. при наложении заклинания, и код, уменьшающий атаку на 3 ед. при снятии заклинания. Вот эти участки кода: Как видите, код на двух картинках мало чем отличается. Давайте разберёмся, что делает каждая из инструкций. 1. mov eax, [ebp+var_8] Эта инструкция загружает в регистр eax адрес отряда внутри combatManager - специальной структуры данных, в которой хранится вся (ну или почти вся) информация о текущей битве. На самом деле, эта инструкция выглядит так: mov eax, [ebp-8] (вы можете привести инструкцию к этому виду, установив курсор в строчку с этой инструкцией и нажав клавишу K, повторное нажатие клавиши вернёт инструкцию к первоначальному виду). var_8 - это просто одно из удобных обозначений для локальных переменных функции, которые хранятся в стеке. Если интересно, наведите курсор на имя локальной переменной var_8 и Вы увидите, какие ещё переменные использует функция, а также аргументы, передаваемые этой функции через стек (чтобы увидеть весь список, прокрутите колёсико мыши вниз, пока не увидите надпись "end of stack variables"). 2. mov cl, [eax+0C6h] Мы знаем, что после выполнения предыдущей команды, в регистре eax окажется адрес отряда внутри структуры combatManager ("Менеджер битвы" по-русски). Тогда что хранится по адресу eax + 0C6h (0C6h = 198)? Очевидно, там хранится что-то, что находится внутри этой структуры Нетрудно проверить, что на "расстоянии" в 198 байт от начала структуры с информацией об отряде хранится атака этого отряда. Она-то и помещается в регистр cl. 3. add cl, 3 Здесь значение регистра cl увеличивается на 3. 4. mov edx, [ebp+var_8] В регистр edx помещается адрес отряда, с которым работает следующая за ней инструкция. Избыточная инструкция: адрес текущего отряда никуда не исчез из регистра eax, и следующая инструкция могла бы работать с регистром eax, а не использовать ещё один регистр (edx). 5. mov [edx+0C6h], cl Нетрудно догадаться, что эта инструкция делает то же, что и инструкция mov cl, [eax+0C6h], но только в обратном направлении: значение регистра cl записывается обратно в оперативную память. 6. jmp short loc_41FC2D Благодаря этой инструкции управление передаётся дальше, в нужное место программы, т.е. следующей будет выполнена инструкция, расположенная по адресу 41FC2D. Аналогично разбираются инструкции на второй картинке. В принципе, отличие там одно: вместо сложения (add) выполняется вычитание (sub). Теперь давайте немного оптимизируем код, т.е. уберём лишнюю инструкцию mov edx, [ebp+var_8], а также подправим следующую за ней. Таким образом мы получим более короткий код, который будет делать всё то же самое, что делает код, изображённый на первой картинке. Кроме того, напротив каждой инструкции запишем её машинный код после знака ";" (знак комментария в FASM'е).
Я поставил знак вопроса напротив инструкции mov [eax+0C6h], cl, т.к. посмотреть её машинный код негде (вместо неё у нас есть старая инструкция mov [edx+0C6h], cl. Существуют правила формирования машинных кодов по ассемблерным инструкциям, но они пока нам не понадобятся, ведь мы собрались менять урон, а не оптимизировать код А раз мы хотим поменять урон, придётся немного переделать вышеприведённый фрагмент кода. Первая инструкция нас устраивает: в регистр eax загружается адрес отряда внутри "менеджера битвы", а он, как Вы сами понимаете, не изменился и по-прежнему хранится во всё той же локальной переменной var_8. А вот дальше будут существенные изменения. Если Вы вернётесь теперь к части первой данной статьи и посмотрите на дамп оперативной памяти, то увидите, что за атакой отряда идёт его защита, потом - минимальный урон, а за ним - максимальный урон. Поэтому, чтобы загрузить в регистр cl, к примеру, значение защиты отряда, необходимо будет изменить вторую инструкцию на mov cl, [eax+0C7h] (т.е. мы помещаем в регистр cl "то, что находится на 1 байт дальше атаки"). Поэтому, чтобы в регистр cl попал урон, нам понадобятся инструкции: mov cl, [eax+0C8h] (для загрузки минимального урона) mov cl, [eax+0C9h] (для загрузки максимального урона) Команда увеличения значения в регистре cl останется без изменений: add cl, 3 (вместо 3 можно прописать Ваше значение). А четвёртая команда поменяется на: mov [eax+0C8h], cl (для записи увеличенного минимального урона обратно) mov [eax+0C9h], cl (для записи увеличенного максимального урона обратно) В результате мы получим следующий код:
Вот только как прописать вместо старого машинного кода новый, ведь наверняка он окажется больше по размеру? Удалив избыточную инструкцию (mov edx, [ebp+var_8]) мы освободили всего лишь 3 байта, которые она занимала, а наши новые инструкции займут гораздо больше 3 байтов (одна только дополнительная инструкция add cl, 3 "съест" освобождённые 3 байта). Хотя и существуют методы, позволяющие вставить в исполняемый файл игры вышеприведённый код полностью, их описание выходит за рамки данной статьи Поэтому мы пойдём другим путём. Оригинальный фрагмент кода (см. первую картинку) занимает 3 + 6 + 3 + 3 + 6 + 2 = 23 байта (просто просуммируйте размеры машинных кодов, соответствующих инструкциям на картинке), поэтому мы должны попробовать ужать наш новый код до этого (или меньшего) размера. Сделать это, не зная языка ассемблера, будет проблематично, поэтому я только приведу полученный результат. Воспользуемся тем, что значения минимального и максимального урона следуют друг за другом, а поэтому могут быть обработаны одновременно:
Первая инструкция не претерпела никаких изменений и по-прежнему загружает в регистр eax адрес отряда внутри "менеджера битвы". А вторая... делает всё остальное Давайте теперь посчитаем размер нового кода. Для этого необходимо открыть FASM и набрать в нём наш код, не забыв указать, что он предназначен для 32-битных процессоров (x86), с помощью директивы use32:
Далее необходимо скомпилировать данный фрагмент кода. Нажмите Ctrl+F9, и FASM предложит сохранить листинг "программы" в файле на диске. Задайте имя файлу (советую завести для листингов отдельную папку) и Вы увидите следующее сообщение: Как видно, наш код занял всего 12 байтов Теперь откройте папку с сохранённым листингом (файл с расширением .ASM) и увидите там другой файл с именем, совпадающим с именем листинга, но уже c другим расширением (.BIN). Откройте его с помощью шестнадцатеричного редактора и увидите там машинный код, соответствующий только что введённым инструкциям. Его-то и нужно будет перенести в исполняемый файл игры. Теперь осталось только разобраться, что делать с "хвостом" старого кода до инструкции jmp short loc_41FC2D, а также написать код для корректного возвращения урона отряда к исходным значениям после снятия заклинания "Жажда крови". Для этого замените инструкцию add на sub:
Обратите внимание на то, что первая строчка кода тоже изменилась! Теперь получите машинный код в FASM'е. А с остатком старого кода ("хвостом") можно поступить двумя способами: а) дописать инструкцию jmp short loc_41FC2D непосредственно после нашего кода; б) заменить "хвост" пустыми инструкциями nop до инструкции безусловного перехода jmp short loc_41FC2D. На первый взгляд, первый способ кажется проще. Действительно, в чём проблема дописать после нового кода два байта: EB 71? Но всё дело в том, что адрес перехода в команде jmp является относительным, поэтому, если мы хотим вставить инструкцию jmp по другому адресу, придётся пересчитать также и относительный адрес перехода. Сделать это сравнительно просто, но я не хочу нагружать Вас дополнительной информацией, поэтому мы просто "занулим" остатки старого кода пустыми инструкциями nop (90), а инструкцию jmp short loc_41FC2D оставим без изменения, хотя это и не самое элегантное решение. А теперь давайте просто сделаем, чтобы работало 1. Откройте исполняемый файл игры в шестнадцатеричном редакторе и перейдите по адресу первой инструкции на первой картинке: 0001FBA5 (он виден слева в статусной строке, если установить курсор на инструкцию). 2. Откройте машинный код (первый сохранённый файл с расширением .BIN), соответствующий первому написанному нами фрагменту кода:
Если что-то не получилось, то вот он: 8B 45 F8 66 81 80 С8 00 00 00 03 03 (вторая команда длиннющая, но всё равно короче других вариантов). Введите его по адресу 0001FBA5. В WinHex'е можно просто скопировать: Edit -> Copy Block -> Hex Values, чтобы скопировать выделенный фрагмент, или Edit -> Copy All -> Hex Values, чтобы скопировать всё, а затем вставить в нужное место: Edit -> Clipboard Data -> Write, но я советую ввести пока вручную. 3. Теперь "занулим" старый код до инструкции jmp short loc_41FC2D, т.е. до EB 71. В результате должно получиться так: Аналогично поступаем со вторым фрагментом: 1. Переходим по адресу первой инструкции на второй картинке, т.е. по адресу 0001F9F3. 2. Открываем машинный код (второй сохранённый файл с расширением .BIN), соотвествующий второму написанному нами фрагменту кода:
Если что-то не получилось, то вот он: 8B 45 FC 66 81 A8 C8 00 00 00 03 03. Вводим его по адресу 0001F9F3. 3. "Зануляем" остатки старых инструкций. Если всё сделано правильно, должно получиться так: Осталось только сохранить изменённый исполняемый файл игры и убедиться, что всё работает. Да, если хотите увеличить урон не на 3 ед., а на 30 ед., измените два последних байта (03 03) в обеих командах (add и sub) на 1E 1E. В заключение отмечу, что прирост урона в окне с информацией об отряде Вы не увидите, а сможете проверить внесённые изменения только на практике. Дело в том, что игра не предусматривает модифицирование базового урона прямо во время боя (повесьте "Благословение" и поймёте, о чём я говорю), а поэтому отображает "железно" прописанный базовый урон для каждого отряда. Однако Вы можете увидеть разницу в уроне между оригинальной версией и изменённой в статусной строке при атаке. Разумеется, можно сделать и так, чтобы изменённый урон отображался также в информационном окне, но на сегодня, видимо, хватит * * * P. S. Test responsibly Обо всех проблемах сообщать в этой теме. Последний раз редактировалось AlexSpl 23 окт 2022, 01:20, всего редактировалось 3 раз(а).
|
Re: Heroes2 - вставляем свои аватарыВот, кстати, нашёл бесплатный шестнадцатеричный редактор с возможностью редактирования оперативной памяти: HxD.
|
|
Re: Heroes2 - вставляем свои аватарыЯ очень ценю ваше терпение и желание быть КРАЙНЕ ясным и последовательным.
К сожалению даже приведенная к такому виду информация, не ложится ровно на тот уровень знаний который у меня есть. Поэтому я сейчас азадам кучу тупых вопросов, на часть которых возможно я найду ответ сам. Но без этого -нету ясности и мне некуда укладывать новую информацию. 1) На чем написан Хирос ? 2) Какой программой мы смотрим и правим сам код игры ? 3) Я так понимаю что Hex - это любой программный код в байтах ( то есть как если бы разложить вещество на атомы) 4) Что из софта вы используете в третей части для удаления части кода и подстановки нулей ? 5) Зачем вы нашли бесплатный шестнадцатеричный редактор с возможностью редактирования оперативной памяти ? Это альтернатива winhex ? чтобы не юзать WinHex + FreeHexEditor ( кстати поиск в FreeHexEditor ещё проще чем вы написали ранее - просто слева в столбце строк -тупо вводим свою строку ) 5) Зачем мне FASM'е чем он отличается от IDA ? 6) Правильно ли я понимаю что хирос написан на ассемблере - и знай мы куда вносить изменения нам бы не понадобился Winhex c его дамбом оперативки ? 7) Зачем помимо обычных команд хироса- требуется знать машинные ( если я правильно понмаю, то есть они же в hex ) Разве в обычные команды мы не можем внести изменения ? 8) Могли бы мы для всего этого обойтись одной программой каким-нибуть дизассемблером с дамбом оперативки и hex-ректором в купэ ? |
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2