Wake of Gods Forum | Форум Во Имя Богов
Программирование ВОГ - Printable Version

+- Wake of Gods Forum | Форум Во Имя Богов (http://wforum.heroes35.net)
+-- Forum: Герои Меча и Магии 3.5 WoG/ERA (/forumdisplay.php?fid=99)
+--- Forum: Обсуждение WoG (/forumdisplay.php?fid=69)
+--- Thread: Программирование ВОГ (/showthread.php?tid=1083)


Программирование ВОГ - Дьякон - 25.02.2010 00:15

Расставлю точки над И по поводу городов. Технические аспекты реализации - готовы давно. Т.е. вопросов типа " а как сделать то или то" уже не осталось. В связи с некоторым застоем в команде я изучаю другие языки программирования и вебпрограммирование. Решил переписать свой исходный код на с++. При переписывании я обдумал еще раз механизм встраивания и принял координально новое решение, что потребовало некоторых исследований и тестов. Я близок к релизу данного продукта. В чем его особенность? Это:

1. Программа патч, которая добавляет новую секцию в ехе (для совместимости с остальными модами как MoP или разрешения Бараторча, которые используют пустые места в конце секций)

2. Монстр создается специальным GUI редактором, в котором описываются св-ва монстра и структура CrAnim. Все максимально автоматизировано и сделано дружелюбно для пользователя. GUI редактор создает файл, в котором хранятся данные о монстре о CrAnim, хранится графика портретов (портреты пакуются в дефы с одним или двумя pcx файлами). Название файла не имеет расширения и хранится в корневом каталоге героев в папке DATA_MONSTR. Название файла и есть номер нового монстра (например, файл с названием "213"). Хранение портеретов в файле обусловлено тем, что номер портрета зависит от номера монстра и каждый раз перелопачивать деф портретов юзерам будет неудобно.

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

4. Все исходные коды и инструменты будут выложены вместе с релизом, что позволит любому исправить и дополнить данный проект.

5. Я постараюсь написать справку и максимально прокомментировать код.

   Если не умру, то постараюсь закончить скоро. Естно на мою скорость влияют заказы от студентов, работа, просто усталость после работы, лень, моя личная жизнь. Но, если не умру то встраивание Бастиона закончу. Когда работа кипит на всех фронтах, то продвижение идет быстро. Мы с Корвином за 3 дня продвинулись от моих скудных наработок под Хоту до Ролика игры при чем без всякого монтажа.

Город тоже собираюсь переписывать на С++.

Спасибо за внимание.


RE: Обсуждение - обо всём - etoprostoya - 25.02.2010 01:12

Спасибо за труд!


RE: Обсуждение - обо всём - Shihad - 25.02.2010 09:20

Прекрасные вести с полей. Надеемся на скорый урожай.


RE: Обсуждение - обо всём - baratorch - 25.02.2010 16:11

Супер.

Кстати щас мой патч ничего не пишет в хвост секции. Пишет вместо 3-х функций, которые выполняют плавное затемнение старого экрана и плавное возникновение из темноты нового при переходе между окнами, между видеороликами и окнами; и вместо функции, которая рисует кусок рва(/колючек/лавы/..) на ногах монстра, когда он на нем стоит.

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

А вообще я хочу сделать визуальный редактор интерфейса в героях, чтобы геройские окна можно было редактировать как формы/диалоги в MS VS. И естественно хочу реализовать добавление нормальных геройских кнопок и, возможно, кастом элементов управления.

Кстати, тут есть тема о программирвании? Имеется пара вопросов..


RE: Обсуждение - обо всём - Berserker - 25.02.2010 16:30

Моё мнение: идти через секции громоздко, неудобно и просто тупо.


RE: Обсуждение - обо всём - etoprostoya - 25.02.2010 16:36

Старенькая тема по программированию.
http://wforum.heroes35.net/showthread.php?tid=810

Вместо "просто тупо", лучше бы предложил что-нибудь. Хоть те же ДЛЛ.


RE: Обсуждение - обо всём - baratorch - 25.02.2010 16:38

через что идти не тупо?


Программирование ВОГ - baratorch - 25.02.2010 16:52

Я ща переписываю свой HD патчер из С#.NET в С++ (чистый Win32 API).
Возникла трудность, точнее недостаток знаний. Подскажите инструмент, который бы мне позволил получить список всех *.exe файлов в папке из которой заущена программа.. ну или хотя бы просто в заданной папке.


RE: Обсуждение - обо всём - Corwin - 25.02.2010 16:53

Quote:Старенькая тема по программированию.
http://wforum.heroes35.net/showthread.php?tid=810
Нет, эта тема не годится.
У нас есть своя в закрытой секции, тут ещё не создавалось.

baratorch, создавай новую тему программирования в разделе "Обсуждение ВОГ"
Добавлено:
Upd
Выделил твоё сообщение в новую тему.


[split] Обсуждение - обо всём - Berserker - 25.02.2010 17:13

Не тупо через DLL. А повторять это уже надоело. Дьяка, как видишь, не переубедил.


RE: Программирование ВОГ - etoprostoya - 25.02.2010 17:42

http://www.cyberguru.ru/cpp-sources/files-folders/poisk-fajlov-i-izmenenie-atributov.html
Находит список файлов по расширению в заданной или текущей папке (szDirPath[]=NULL).


RE: Программирование ВОГ - baratorch - 25.02.2010 20:05

спасибо большое


RE: Обсуждение - обо всём - Дьякон - 25.02.2010 20:42

Все и так через длл, но повторять это надоело - Берсеркер не понимает ))))


RE: Обсуждение - обо всём - Berserker - 25.02.2010 22:17

Толку от длл при добавлении секции? Так пиши весь код в ней, как ZVS.


RE: Обсуждение - обо всём - packa - 25.02.2010 22:22




RE: Обсуждение - обо всём - Berserker - 25.02.2010 23:16

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


RE: Обсуждение - обо всём - Berserker - 25.02.2010 23:34

Можно сделать мини-Эру для Сода с поддержкой загрузки плагинов из папки и без других фич.


RE: Обсуждение - обо всём - Дьякон - 25.02.2010 23:47

К сожалению подгрузкой просто длл не всегда можно справиться со всеми задачами.


RE: Обсуждение - обо всём - Berserker - 25.02.2010 23:58

Quote:К сожалению подгрузкой просто длл не всегда можно справиться со всеми задачами.
Назови хоть одну задачу.


RE: Обсуждение - обо всём - Дьякон - 26.02.2010 00:13

Например нужно обрабатывать результаты какой-нибудь функции. При этом прописывая код начиная с команды retn ты затираешь кодом нижеследующую процедуру.


RE: Обсуждение - обо всём - Berserker - 26.02.2010 00:17

Банальный перехват до ret с несколькими командами на твою функцию в DLL, в которой реализуется двухуровневый обработчик:

1) Уровень асма
PUSHAD
PUSHFD
...получить параметры
...вызвать высокоуровневый обработчик
POPFD
POPAD
...выполнить затёртые команды, что были до RET
RET

2) Уровень твоего высокоуровневого обработчика.


RE: Обсуждение - обо всём - asm - 26.02.2010 00:20

(26.02.2010 00:13)Дьякон Wrote:  Например нужно обрабатывать результаты какой-нибудь функции. При этом прописывая код начиная с команды retn ты затираешь кодом нижеследующую процедуру.

Можно начать раньше, а эти 5 байт повторить с своей ДЛЛ, оч удобно... у меня ДЛЛ изменяющий игру скоро будет весить больше самой игры )))) куда ж это раместишь с ехе ))))
Добавлено:
(26.02.2010 00:17)Berserker Wrote:  Банальный перехват до ret с несколькими командами на твою функцию в DLL, в которой реализуется двухуровневый обработчик:

1) Уровень асма
PUSHAD
PUSHFD
...получить параметры
...вызвать высокоуровневый обработчик
POPFD
POPAD
...выполнить затёртые команды, что были до RET
RET

2) Уровень твоего высокоуровневого обработчика.

Берс опередил....

Берсу ещё раз спасибо. Если бы не его изыскания и терпение над моими глупыми вопросами, то не было бы моего мода


RE: Обсуждение - обо всём - Дьякон - 26.02.2010 00:29

1. Результат - это eax.
2. Eax заполняется перед самым ret.
3. При вызове процедуры высокого уровня портятся регистры. Например, push esp, mov ebp, esp.
4. Выполнить затертые команды до ret? И что ты не влезишь на процедуру следующую? Где ты выиграл в размерах? Что начиная с ret, что до ret?
5. Использовать пустые места? Это время на их поиск и отладку программы, чтоб все учитывалось при патче + связь с высоким уровнем. + кто-то уже занял пустые места своим патчем и игра слетает с катушек.

А теперь мой вариант:
20 строк кода и новая секция. Далее нужно лишь вычислить offset для jmp и заменить команду ret. Переходим в новую сецию. Для заполнения новой секции воспользуемся удобным масмом (а не асмом встроенном в с++). Создаем объектный файл, указываем линкеру путь к этому файлу, описываем процедуру и memcpy записывает нужный нам код в секцию, который мы без труда, без глубокого вникания в опкоды написали на масме.
Добавлено:
В общем спор бессмысленный. Каждый останется при своем мнении. Я много чего пробовал и вышепредложенные варианты меня не устроили. Пишу так как удобно и быстрее вот и все. Я исходники выложу, захотите исправляйте в соответствии с вашими взглядами )))))


RE: Обсуждение - обо всём - Berserker - 26.02.2010 00:38

Приведи хоть один адрес и нужный перехватчик. Я приведу тебе полный код. У ЗВС такого кода былоьше 30 тыс. строк, у меня в эре перехватчиков больше 20, включая возвратные.


RE: Обсуждение - обо всём - Berserker - 26.02.2010 00:49

Дьяк поставил задачу написать перехватчик 0x55D102. ЕАХ - указатель на класс. Его высокоуровневая функция будет менять поля класса.

В бой:
Code:
HookCode(Ptr($55D102), @MuFuncAsm, C_HOOKTYPE_JUMP, 7);

FUNCTION MyFuncAsm; ASSEMBLER; {$FRAME-}
ASM
  // Старый код
  MOV [DWORD FS:0],ECX
  MOV ESP,EBP
  PUSHAD
  PUSHFD
  PUSH EAX
  CALL MyFunc
  POPFD
  POPAD
  // RET
END;

PROCEDURE MyFunc (Obj: PSomeObj);
BEGIN
  ShowMessage(Obj.DefName);
END;



RE: Программирование ВОГ - GrayFace - 26.02.2010 05:57

И на с++ Sm При условии, что в 55D0F8 вставляется jmp
Code:
void* __stdcall LoadDefHook(void* def)
{
  return def;
}

__declspec(naked) void _LoadDefHook()
{
  __asm
  {
    mov large fs:0, ecx
    push eax
    call LoadDefHook
    push 0x55D0FF
    ret
  }
}



RE: Программирование ВОГ - baratorch - 26.02.2010 17:55

вроде суть перехвата и подмены понял и оценил
только вот я в жизни не создал ни одной длл и проект полностью себе не представляю
куда мне пихать вызовы HookCode (в примере Берсекера), в DllMain ?

и каков код самой HookCode??

В екзешник героев мне надо будет вставить вызов LoadLibrary моей длл, так?


RE: Программирование ВОГ - SAG - 26.02.2010 18:02

вот пример http://collabedit.com/display?id=15964


RE: Программирование ВОГ - Berserker - 26.02.2010 19:10

baratorch, вы на чём пишите? И могли бы привести пример, что и на что нужно пропатчить? Пример сага компилируется через Era Source\BIN.W32\VP.EXE. Выходной файл в Era Source\OUT.W32\.

Костяк DLL в принципе шаблонный.


RE: Программирование ВОГ - etoprostoya - 26.02.2010 19:14

baratorch пишет на С (или С#), так что VP.EXE ему не поможет.


RE: Программирование ВОГ - Berserker - 26.02.2010 19:46

Quote:пишет
Он писал, что не программист и даже DLL не создавал. Так что в данном случае "пишет" = максимум ознакомиться с синтаксисом языка и что-то простое вроде hello world.

Каркас аналога на СИ++ нужно попросить Сержа написать.


RE: Программирование ВОГ - baratorch - 26.02.2010 20:24

ну, хело ворлд эт канешн.. )))). Я по образованию и профессии - не ИТэшник. А вот по самообразованию и призванию - программер. Программированием увлекаюсь с 6-го класса школы. Были времена, когда я полностью забивал на прграммирование, но совсем избавиться от этого увлечения не могу, как ни стараюсь Sm

Я могу не знать чего-то (что можно найти в справочной литературе), но вот с навыками то у меня все более чем в порядке, а ведь это самое главное! так ведь?

так что я пишу, пишу на С#, C++ в MS VS,
когда-то давно еще писал на VB6 и VB.NET. Ну и со школы паскаль помню, так что примера SAG'a достаточно, прочитать смогу. Спасибо!

Я конечно и сам разобраться во всем могу, но ведь с вашей помощью то намного быстрее и легче!Большое всем спасибо!


RE: Программирование ВОГ - feanor - 26.02.2010 20:26

Quote:Каркас аналога на СИ++ нужно попросить Сержа написать.
Когда (если?) доперепишу - выложу простенький пример на С.


RE: Программирование ВОГ - Berserker - 26.02.2010 20:28

Я было удивился, как "не ИТ-шник" так рьяно вошёл в сферу модинга 132
Вчера разговаривал с Дьяком по поводу встраивания нового города. Посоветовал патчить ехе после вога из DLL, чтобы гарантированно быть совместимым с другими проектами. Правда, ему придётся коренным образом многое переписать, не знаю, пойдёт ли на это.


RE: Программирование ВОГ - ZURG - 26.02.2010 20:30

Мне в своё время помогли статьи на wasm.ru
http://wasm.ru/article.php?article=pemodify (Модификация исполняемых PE-файлов)
http://wasm.ru/series.php?sid=17 («Введение в крэкинг с нуля, используя OllyDbg»)
по первой ссылки вроде как раз то что надо.


RE: Программирование ВОГ - asm - 27.02.2010 00:12

baratorch, готов помочь во встраивании функционала в игру. У меня есть опыт написания большой ДЛЛ
http://www.heroeswt.net/features.php

В своё время обучал САГа этому делу с помощью скайпа и РАдмина, достаточно продуктивно.

В свою очередь есть ряд пожеланий по функционалу: хочу что потом можно было не сложно интегрировать в мой мод. И по этому поводу есть идеи как сделать универсально.

Моя аська 343-425-087


RE: Программирование ВОГ - feanor - 27.02.2010 15:36

Sample.rar
Cтавится хук на подсказки в окне юнита.

Code:
#include "main.h"

#include <windows.h>
#include <stdio.h>

#define OPCODE_JUMP 0xE9
#define OPCODE_CALL 0xE8
#define OPCODE_NOP 0x90

#define HOOKTYPE_JUMP 0
#define HOOKTYPE_CALL 1

#define HOOK_SIZE 5


inline void NopMem(void *mem, int size)
{
    memset((void*)mem,OPCODE_NOP,size);
}

inline void WriteHook( void *pOriginal, void *pNew, char type )
{
    *(byte*)pOriginal = (type==HOOKTYPE_JUMP)?OPCODE_JUMP:OPCODE_CALL;
    *(void**)( (byte*)pOriginal + 1 ) = (void*)( (byte*)pNew - (byte*)pOriginal - HOOK_SIZE );
}

#define MSG_OK 1
#define MSG_YES_NO 2
#define MSG_RIGHT_CLICK 4


__fastcall int (*ShowMSG)(const char *text, int type, int f1, int f2, int f3, int f4, int f5, int f6, int f7, int f8, int f9, int f10) =
      (__fastcall int (*)(const char*, int, int, int, int, int, int, int, int, int, int, int))(0x4F6C00);

__cdecl void  (*CallERM)(int num) =
        (__cdecl void(*)(int))(0x74CE30);

#define URMB_NAME_AREA           0x0D
#define URMB_DEFENCE_AREA        0x95
#define URMB_ATTACK_AREA         0x97
#define URMB_DAMAGE_AREA         0x78
#define URMB_SHOTS_AREA          0x7B
#define URMB_HP_AREA             0x6B
#define URMB_CURRHP_AREA         0x29
#define URMB_SPEED_AREA          0x5A
#define URMB_EFFECTS_AREA        0x3D //действующие заклятья
#define URMB_DISMISS_AREA        0x39 //кнопка "Уволить"
#define URMB_OK_AREA             0x72 //кнопка "Ок"
#define URMB_UPGRADE_AREA        0x30 //стрелки апгрейда
#define URMB_MAGIC_AREA          0x14 //кнопка каста у волшебных драконов
#define URMB_NUMBER_AREA         0x23 //количество существ в стеке


BOOL NewMsg(unsigned char type, int unit)
{
    char buf[200];
    if(type==URMB_NAME_AREA)
    {
        sprintf(buf,"%02X %i", type, unit);
        ShowMSG(buf,MSG_RIGHT_CLICK,-1, -1, -1, 0, -1, 0, -1, 0, -1, 0);
        return true;
    }

    if(type==URMB_MAGIC_AREA)
    {
        ShowMSG("Колдовать/атаковать",MSG_RIGHT_CLICK,-1, -1, -1, 0, -1, 0, -1, 0, -1, 0);
        return true;
    }

    if(type==URMB_EFFECTS_AREA)
    {
        CallERM(4001);
        return true;
    }
   return false;
}


__fastcall int hook_5F4E84(const char *text, int type, int f1, int f2, int f3, int f4, int f5, int f6, int f7, int f8, int f9, int f10)
{

    register void *eax asm("eax");
    register void *ebx asm("ebx");
    unsigned char unit = ((char*)ebx)[0x60];

    if(NewMsg((int)eax,unit))
       return 0;
    else
       return ShowMSG(text, type, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10);
}




extern "C" __stdcall BOOL DllMain( HINSTANCE hInstanceDLL, DWORD Reason, void *pReserved )
{
    switch (Reason)
    {
        case DLL_PROCESS_ATTACH:
        {
        WriteHook((void*)0x5F4E84,(void*)hook_5F4E84,HOOKTYPE_CALL);
        } break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
}



RE: Программирование ВОГ - baratorch - 27.02.2010 20:43

asm, feanor, спасибо, я уже разобрался. Уже начал переписывать свой патч в длл.

Разбирался.. - воткнул вызов LoadLibrary в WinMain героев, а где он воткнут в Эре? в WT?

asm, аськой я принципиально не пользуюсь, мой ник в скайпе такой же как здесь.


RE: Программирование ВОГ - Berserker - 27.02.2010 21:04

Quote:а где он воткнут в Эре?
Немного далее OEP вога. За 701000. Сама DLL выполняет после инициализации затёртый код.


RE: Программирование ВОГ - baratorch - 27.02.2010 22:10

спасибо.

вопрос тут возник.

вот в примере SAGa функция WriteAtCode использует VirtualProtect для того чтобы разрешить запись именно в те байты памяти, которые меняются, а потом восстанавливает к ним иходный доступ.

А если мой патч вызывает например миллион этих WriteAtCode.... не лучше ли сделать один вызов VirtualProtect для разрешения записи в весь геройский код, потом миллион патчей, и затем один VirtualProtect для восстаовления исходного доступа к всему геройскому коду.
Можно так? Что будет быстрее (рациональнее для машины) работать?
Что думаете?


RE: Программирование ВОГ - etoprostoya - 27.02.2010 22:21

Так было бы оптимально. Один вызов на несколько патчей.


RE: Программирование ВОГ - Berserker - 27.02.2010 22:28

Я предпочитаю корректность. Но если все страницы патчинга имеют одни атрибуты, то почему бы и нет.


RE: Программирование ВОГ - asm - 27.02.2010 22:43

а можно вообще не протектить, т.к. в тот момент когда ты изменяешь, не думаю что др. потоки читают.
А в целом более корректно заблочить всё, как в БД - 1 транзакция на все изменения.


RE: Программирование ВОГ - Berserker - 27.02.2010 23:39

Асм, ты про что? Не нужно ничего блочить и потоки ни на что не влияют.


RE: Программирование ВОГ - etoprostoya - 27.02.2010 23:41

Ну разве что антивирус (как поток) иль ещё кто захочет проверить что там за экзешник патчится.


RE: Программирование ВОГ - baratorch - 28.02.2010 00:36

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

Code:
class Code
{
private:
    static DWORD protect;
    static LPVOID adress;
    static SIZE_T size;

public:
    enum HOOK_TYPE
    {
        JUMP, CALL
    };

    static void BeginWrite(DWORD adress, DWORD size);
    static void EndWrite();

    static void Write(DWORD adress, BYTE value);
    static void Write(DWORD adress, WORD value);
    static void Write(DWORD adress, DWORD value);
    static void WriteAdd(DWORD adress, DWORD value);
    static void Hook(DWORD adress, LPVOID procedure, HOOK_TYPE type);
};

Code:
void Code::BeginWrite(DWORD a, DWORD s)
{
    adress = (LPVOID)a;
    size = (SIZE_T)s;
    VirtualProtect(adress, size, PAGE_READWRITE, &protect);
}

void Code::EndWrite()
{
    VirtualProtect(adress, size, protect, NULL);
}

void Code::Write(DWORD adress, BYTE value)
{
    *(LPBYTE)adress = value;
}

void Code::Write(DWORD adress, WORD value)
{
    *(LPWORD)adress = value;
}

void Code::Write(DWORD adress, DWORD value)
{
    *(LPDWORD)adress = value;
}

void Code::WriteAdd(DWORD adress, DWORD value)
{
    *(LPDWORD)adress += value;
}


void Code::Hook(DWORD adress, LPVOID procedure, HOOK_TYPE type)
{
    if (type == HOOK_TYPE::JUMP)
        Write(adress, (BYTE)0xE9); //write JMP opcode
    else //if (type == HOOK_TYPE::CALL)
        Write(adress, (BYTE)0xE8); // write CALL opcode
    Write(adress + 1, (DWORD)procedure - adress - 5);
}

Code:
void Patch()
{

// ...

    Code::BeginWrite(0x401000, 0x239000);

// ...

    // ADVMAN window size - FS
    Code::Write((0x401530 + 1), (DWORD)screen_Height);
    Code::Write((0x401537 + 1), (DWORD)screen_Width);

    // ADVMAN window: world view size
    Code::WriteAdd((0x401608 + 1), (DWORD)common_stretching_Y);
    Code::WriteAdd((0x40160d + 1), (DWORD)common_stretching_X);

// ...

    Code::EndWrite();
}



RE: Программирование ВОГ - etoprostoya - 28.02.2010 00:45

Наверное, лучше вместо перегрузки Write, сделать Write32, Write16, Write8 или WriteDword, WriteWord, WriteByte. Дабы не запутаться и нагляднее. Но это дело привычек, вкуса. По-моему, так класс - это лишнее.
Добавлено:
Я так говорю, потому что предпочитаю С, а не С++.


RE: Программирование ВОГ - baratorch - 28.02.2010 00:58

Quote:Наверное, лучше вместо перегрузки Write, сделать Write32, Write16, Write8 или WriteDword, WriteWord, WriteByte. Дабы не запутаться и нагляднее
согласен, так и сделаю

Ну класс здесь вобщем-то и не класс, он выступает в роли namespace, и просто объединяет по смыслу несколько функций. Он для той же наглядности.


RE: Программирование ВОГ - GrayFace - 28.02.2010 09:38

А в ВоГе и без VirtualProtect код Героев можно менять.


RE: Программирование ВОГ - baratorch - 28.02.2010 12:46

блин, оказывается я не могу в VC++ 2005 прямо вызвать геройскую функцию.
т.е. вот таким образом:

call 0x41AFA0

пришлось извратится вот так:

Code:
typedef void (*SIMPLE_FUNC)(void*);

SIMPLE_FUNC Func_41AFA0 = (SIMPLE_FUNC)0x41AFA0;

void ModFunc_41AFA0()
{
    __asm
    {
        push ebp
        mov ebp, esp
        mov eax, dword ptr ss:[ebp+0x18]
        push eax
        mov eax, dword ptr ss:[ebp+0x14]
        push eax
        mov eax, dword ptr ss:[ebp+0x10]
        push eax
        mov eax, dword ptr ss:[ebp+0x0c]
        add eax, common_centering_Y
        push eax
        mov eax,dword ptr ss:[ebp+0x08]
        add eax, common_centering_X
        push eax
        call Func_41AFA0
        pop ebp
        retn 0x14
    }
}

может все-таки можно это сделать прямо?


RE: Программирование ВОГ - feanor - 28.02.2010 19:41

Quote:может все-таки можно это сделать прямо?
указатель на функцию с явным указанием способа передачи параметров?


RE: Программирование ВОГ - Berserker - 28.02.2010 19:46

Угу. На Паскале:
Code:
TSomeFunc = PROCEDURE (i: integer; b: boolean); STDCALL;
VAR f: TSomeFunc;

f:=TSomeFunc($401000);
f(5, TRUE);



RE: Программирование ВОГ - Дьякон - 01.03.2010 20:51

На с++

    typedef void (*PFUNC) (int i);
    PFUNC pFunc;
   

    pFunc = (PFUNC)0x401000;
    pFunc(i);


RE: Программирование ВОГ - feanor - 01.03.2010 22:34

или так, по типу библиотеки функций:

__fastcall int (*ShowMSG)(const char *text, int type, int f1, int f2, int f3, int f4, int f5, int f6, int f7, int f8, int f9, int f10) =
    (__fastcall int (*)(const char*, int, int, int, int, int, int, int, int, int, int, int))(0x4F6C00);

__cdecl void (*CallERM)(int num) =
    (__cdecl void(*)(int))(0x74CE30);

....
ShowMSG(buf,MSG_RIGHT_CLICK,-1, -1, -1, 0, -1, 0, -1, 0, -1, 0);
CallERM(4001);


RE: Программирование ВОГ - GrayFace - 03.03.2010 21:22

(28.02.2010 12:46)baratorch Wrote:  call 0x41AFA0
А это, по идее, никакой язык не позволит, т.к. смещение будет относительным и при загрузке dll по другому адресу "поплывет".
Достаточно объявить переменную любого подходящего типа. Например,
int SomeHeroesProc = 0x41AFA0

в __asm:
call SomeHeroesProc

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


RE: Программирование ВОГ - baratorch - 03.03.2010 23:59

о, да, я именно об этом спрашивал.

Quote:А это, по идее, никакой язык не позволит, т.к. смещение будет относительным и при загрузке dll по другому адресу "поплывет".

Действительно, как я сам об этом не подумал..

Просто мне хотелось для начала перенести в длл все в точности как у меня было в экзешнике, чтобы было минимум работы и чтобы максимально быстро получить рабочий вариант длл, а потом уже овысокоуровнить всё постепенно. Ну и я в процессе предыдущей работы привык к максимально короткому и эффективному коду и теперь мне все что выдает компилятор vc++ кажется громоздким.

У меня тут еще проблема одна была с внедрением своего высокоуровневого кода в героев, оказывается у меня в настройках проекта все функции по умолчанию были __cdecl (а все геройские то __stdcall), а я этого не знал, не знал вообще что значат эти __cdecl, __stdcall но все же сделал рабочий длл. Теперь придется переделывать, чтобы ничего не было через Ж.

Кстати, как быть с геройискими функциями, у которых один аргумент передается в регистре ecx. Я ж не могу объявить функцию с есх аргументом, да? Тоесть при вызове такой функции из не асм кода все равно предется MOVать в ЕСХ аргумент?

И вот еще вопрос.
Мой патчер из bmp кусочков склеивал картинку под нужное разрешение, и сохранял ее в формате Zsoft PCX в папке Дата. А теперь при переходе на Длл смысла сохранять картинку в файл нет. Нужно чтобы ее клеила Длл и конвертила в формат загруженного героями PCX. В этом формате я вроде бы разобрался, у него вроде как палитра записана 16-ти битными цветами, кто знает какой там формат цвета - 565, 4444 или че другое?

Спасибо!


RE: Программирование ВОГ - etoprostoya - 04.03.2010 00:08

В ECX-регистр по стандарту С++ для функции, принадлежащей классу, засовывается указатель (this) на этот класс. В таком случае имеет смысл создать класс(ы), в который(е) поставляются данные.


RE: Программирование ВОГ - Berserker - 04.03.2010 00:13

ecx - объект, __thiscall. Если ecx и edx содержат первые два параметра процедуры, то это соглашение __fastcall.


RE: Программирование ВОГ - etoprostoya - 04.03.2010 00:22

Quote:On the Microsoft Visual C++ compiler, the this pointer is passed in ECX and it is the callee that cleans the stack, mirroring the stdcall convention used in C for this compiler and in Windows API functions. When functions use a variable number of arguments, it is the caller that cleans the stack (cf. cdecl).



RE: Программирование ВОГ - feanor - 04.03.2010 00:37

Quote:а все геройские то __stdcall
не все.
Quote:Кстати, как быть с геройискими функциями, у которых один аргумент передается в регистре ecx. Я ж не могу объявить функцию с есх аргументом, да? Тоесть при вызове такой функции из не асм кода все равно предется MOVать в ЕСХ аргумент?
Опять таки надо юзать fastcall (см.выше пример с ф-ей показа сообщения), тогда первые два параметра будут в ecx и edx.
Quote:On the Microsoft Visual C++ compiler, the this pointer is passed in ECX and it is the callee that cleans the stack, mirroring the stdcall convention used in C for this compiler and in Windows API functions. When functions use a variable number of arguments, it is the caller that cleans the stack (cf. cdecl).
А разговор идет не о них.


RE: Программирование ВОГ - etoprostoya - 04.03.2010 01:02

Ну тогда сами скажите откуда берётся резервирование ECX (EDX не был упомянут).


RE: Программирование ВОГ - GrayFace - 04.03.2010 23:43

(03.03.2010 23:59)baratorch Wrote:  Мой патчер из bmp кусочков склеивал картинку под нужное разрешение, и сохранял ее в формате Zsoft PCX в папке Дата. А теперь при переходе на Длл смысла сохранять картинку в файл нет. Нужно чтобы ее клеила Длл и конвертила в формат загруженного героями PCX. В этом формате я вроде бы разобрался, у него вроде как палитра записана 16-ти битными цветами, кто знает какой там формат цвета - 565, 4444 или че другое?
55ACAE читает структуру {size, width, height: int}, где size - размер буфера картинки (width*height).
55ACD8 читает буфер картинки (содержит все строки подряд, начиная с 0).
55ACFA читает палитру, по 3 байта на цвет.
Проще всего подменить их + можно запретить в 55AA9A загрузку тех битмапок, которые ты генерируешь.


RE: Программирование ВОГ - baratorch - 05.03.2010 21:48

спасибо, но я пойду своим путем. Он более правильный, т.к. мне в результате понадобится лишь подменять указатель на загруженный РСХ8.

я посмотрел на функцию 44F940 - она рисует загруженный PCX 8 bit на геройскую ~поверхность~ , по ней довольно просто определил структуру уже загруженного PCX8. единственное чего я пока не знаю, это в каков формат 16-битового цвета в героях. Ну это не страшно, найду опытным путем.


RE: Программирование ВОГ - etoprostoya - 05.03.2010 21:51

(05.03.2010 21:48)baratorch Wrote:  единственное чего я пока не знаю, это в каков формат 16-битового цвета в героях.

Не знаю, но может это поможет.
http://forum.df2.ru/index.php?showtopic=15391&view=findpost&p=372080


RE: Программирование ВОГ - Berserker - 05.03.2010 21:58

16 битовый цвет описан в википедии. Reg(5) Green(6) Blue(5) по битам.


RE: Программирование ВОГ - baratorch - 05.03.2010 22:52

Ну я с 565 и начну, просто он еще бывает 4444, или какой-нить экзотический 5551.


RE: Программирование ВОГ - Berserker - 06.03.2010 00:22

Я проверял, в Эре встроен цветной текст. Именно так и работает.


RE: Программирование ВОГ - baratorch - 06.03.2010 01:07

уже все сделал )

загруженный pcx8:
+36 - ширина
+40 - высота
+44 - размер строки (сканлайна)
+48 - указатель на массив пикселей
+80 - палитра - массив из 256 16-битных RGB565 цветов.
на всякий случай я расположил массив пикселей сразу за палитрой, хотя его вроде можно куда угодно засунуть. массив пикселей такой же как у bmp8, только строки в обратном (т.е. в прямом Sm ) порядке.
это все что нужно геройской функции чтоб нарисовать pcx8


RE: Программирование ВОГ - baratorch - 06.03.2010 01:26

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

Никто еще не делал шрифты-мод? Sm
Думаю для ХД это актуально.


RE: Программирование ВОГ - SAG - 09.03.2010 14:26

я рисовал на геройскую поверхность через GetDC, но она разумеется сразу перерисовывается, так что ищу путь сделать хук на WM_Paint. Правда, неясно как замедлится работа приложения из за этого. Было бы круто рисовать сразу на DirectX поверхность, если можешь то дай ее handle.
Практическое применение - создать несколько новых нажимаемых кнопок на карте, статических надписей и т.д.
Шрифты меня вполне устраивают ,альфаблендинг - пока слабо представляю зачем он может понадобиться.


RE: Программирование ВОГ - gamecreator - 09.03.2010 17:52

(09.03.2010 14:26)SAG Wrote:  ищу путь сделать хук на WM_Paint
ну чисто теоретически тут ниче сложного нет. грузишь длл, в дллмейн прописываешь хук и вперед.


RE: Программирование ВОГ - feanor - 09.03.2010 20:21

Quote:создать несколько новых нажимаемых кнопок на карте
зачем для этого изврат с поверхностями?
МОР писал, что лишние кнопки можно в экзешнике нарастить.


RE: Программирование ВОГ - baratorch - 09.03.2010 23:43

Я очень слабо знаком с DirectX, но если я правильно понял внутренности графического движка героев, то я не очень понимаю зачем героям DirectDraw, ибо все в героях рисуется собственными функциями на собственные "поверхности" (то есть все операции в оперативе и с помощью CPU), и только самый последний готовый геройский БэкБуфер летит на экран посредством функцй DirectDraw.

Функция 0x603190 как раз осуществляет этот полет( "поверхность" - в ecx, и 4 аргумента определяют прямоугольник, который должен нарисоваться на экране) к тому же эта функция рисует курсор мыши (теми же геройскими средствами) перед тем как отобразить прямоугольник "поверхности" на экране.

Более того, некоторые графические фильтры в героях ('засерение' карты загадки, окрашивание прямоугольников с числом монстров на поле боя) реализованы через флоатин'-поинт операции, т.е они жутко медленные. Я для прикола применял эти фильтры для всей геройской картинки - игра сильно тормозила (в хайрезе) на 3ГГц CPU.

Геройский бэкбуфер - 0x6992d0, не знаю ДиректДравный ли это Сёрфис, или собственный геройский формат.
Функция 0x603190 в героях вызывается только с этой 0x6992d0 поверхностью.

Ну а добавлять кнопки и надписи можно и нужно геройскими средствами. Так буду делать я.


RE: Программирование ВОГ - etoprostoya - 10.03.2010 00:51

(09.03.2010 23:43)baratorch Wrote:  Более того, некоторые графические фильтры в героях ('засерение' карты загадки, окрашивание прямоугольников с числом монстров на поле боя) реализованы через флоатин'-поинт операции, т.е они жутко медленные. Я для прикола применял эти фильтры для всей геройской картинки - игра сильно тормозила (в хайрезе) на 3ГГц CPU.

А можно узнать адрес этой тормознутой функции-фильтра "засерения"?


RE: Программирование ВОГ - baratorch - 10.03.2010 02:13

int __thiscall sub_44E610(int this_ecx_surface, int x, int y, int width, int height, float a6, float a7)

от a6 и a7 зависит что будет делать функция с прямоугольником изображения - засерит, закраснит, или что другое нехорошее сделает...

помимо того что в ней куча флоатин-поинт вычислений над каждым пикселем, так еще и if-ы и switch на каждый пиксель.


RE: Программирование ВОГ - etoprostoya - 10.03.2010 02:20

Спасибо, посмотрю.


RE: Программирование ВОГ - SAG - 10.03.2010 14:46

(09.03.2010 23:43)baratorch Wrote:  Ну а добавлять кнопки и надписи можно и нужно геройскими средствами. Так буду делать я.
можно подробнее расписать весь процесс?


RE: Программирование ВОГ - etoprostoya - 10.03.2010 15:07

Посмотрел я ту тормознутую функцию... Там в цикле для каждого пикселя происходит три деления (видимо, для каждого компонента цвета), а деление, как известно, самая тормознутая операция всех времён и народов компьютеров.
Но это ещё пол-беды. Настоящая беда программистов из NWC в том, что это деление происходит примерно вот так:

a1 = 7FFFFFFFh/A1;
for(int x = 0; x < X; x++)
{
   for(int y = 0; y < Y; y++)
   {
    mass1[x*Y+y] = mass2[x*Y+y]/a1;
   }
}
Заметили, что сначала находится обратная величина, а потом на эту обратную идёт деление? Этот алгоритм можно оптимизировать и скорость его увеличится в разы, т.к. вместо деления нужно будет использовать умножение, плюс коррекция (а может и без неё прокатит). Если убрать начальные проверки длины и высоты на 0, то можно даже, наверное, вместить в имеющийся размер.
Вот тока я никогда не правил екзешники.


RE: Программирование ВОГ - GrayFace - 10.03.2010 19:21

(06.03.2010 01:07)baratorch Wrote:  уже все сделал )

загруженный pcx8:
+36 - ширина
+40 - высота
+44 - размер строки (сканлайна)
+48 - указатель на массив пикселей
+80 - палитра - массив из 256 16-битных RGB565 цветов.
на всякий случай я расположил массив пикселей сразу за палитрой, хотя его вроде можно куда угодно засунуть. массив пикселей такой же как у bmp8, только строки в обратном (т.е. в прямом Sm ) порядке.
это все что нужно геройской функции чтоб нарисовать pcx8
Там еще есть обычная 3-байтовая палитра, которая вряд ли используется. Про счетчик ссылок и имя не забывай.
00000000 _Pcx_ struc ; (sizeof=0x56C)
00000000 VTable dd ?
00000004 Name db 12 dup(?) ; string©
00000010 field_10 dd ?
00000014 LodItemType dd ? ; = 10 (always?)
00000018 RefCount dd ?
0000001C BufSize dd ? ; w*h
00000020 PicSize dd ? ; w*h
00000024 Width dd ? ; struct offset
00000028 Height dd ?
0000002C ScanlineSize dd ?
00000030 Buffer dd ?
00000034 field_34 dd ?
00000038 field_38 dd ?
0000003C field_3C dd ?
00000040 field_40 dd ?
00000044 field_44 dd ?
00000048 field_48 dd ?
0000004C field_4C dd ?
00000050 DevicePalette dw 256 dup(?)
00000250 Palette _Palette_ ?
0000056C _Pcx_ ends


RE: Программирование ВОГ - baratorch - 10.03.2010 21:04

GrayFace, что за счетчик ссылок?

функция, которая рисует pcx8, обращается только к Height, ScanlineSize, Buffer и DevicePalette, всё остальное не используется.

что за 00000000 VTable? Мне в это поле понадобилось поместить указатель на [(адрес пустой функции) - 4]. В оригинальном PCX вместо пустой функции - деструктор PCXa. Пустышку я подкладываю по причине устройства моей модификации:
Свои ХайРез-PCXы я создаю и конструирую в момент DLL_PROCESS_ATTACH. Затем у меня стоит Хук на геройской функции загрузки PCXa: эта функция загрузки при нужном имени сразу возвращает указатель на мой уже загруженный PCX. А уничтожаются мои PCXы при DLL_PROCESS_DETACH.

(10.03.2010 14:46)SAG Wrote:  
(09.03.2010 23:43)baratorch Wrote:  Ну а добавлять кнопки и надписи можно и нужно геройскими средствами. Так буду делать я.
можно подробнее расписать весь процесс?
'процесса' нету пока. Я над этим работаю.


RE: Программирование ВОГ - SAG - 11.03.2010 18:29

(10.03.2010 21:04)baratorch Wrote:  'процесса' нету пока. Я над этим работаю.
ждемс...это важно. для нормальной игры надо сделать 3-5 кнопок если не больше


RE: Программирование ВОГ - baratorch - 11.03.2010 23:41

хаха! 'Человеческие' новые кнопки в героях!

добавил 3 кнопки на адвенча менеджер и повесил на них 3 функции из диалога адвенча-опшнз. Так же на них можно и подсказки в статус-баре повесить и подсказки-мессаджи по правому клику.
Не надо коментить их расположение, картинки, и то что на них повесил, это всего лишь показательный пример того что могу.
На экран приключений игра позволяет поместить сколько угодно кнопок (думаю в другие окна аналогично).

скачать:
http://sites.google.com/site/heroes3hd/files/SoD_HD_0.99a2.rar?attredirects=0&d=1

инструкция:
распаковать в папку с игрой с установленным ХайРезом версии 0.95 beta 4.
Изменить в файле HiRez.ini разрешенние на нужное (на всякий: кодировка файла должна быть ANSI, разделитель ширины и высоты - латинская малая 'х')
Запускать Heroes3_HD_0.99a.exe


RE: Программирование ВОГ - baratorch - 13.03.2010 23:16

Подскажите пожалуйста, кто знает. Как средствами Win32 API получить список всех разрешений экрана поддерживаемых системой?


RE: Программирование ВОГ - Efrit - 13.03.2010 23:26

Глянь в хелпах про EnumDisplaySettings...


RE: Программирование ВОГ - etoprostoya - 13.03.2010 23:49

Список разрешений экрана только через драйвер видеокарты (и\или монитора). То есть только через DirectX (или OpenGL).

Efrit прав. Нужно перебирать моды в EnumDisplaySettings и получать список возможных разрешений, пока функция возвращает не ноль.


RE: Программирование ВОГ - Дьякон - 23.03.2010 22:39

Поделитесь методами отлова участка кода, который выделил определенную память. Может есть какой-то простой способ?


RE: Программирование ВОГ - GrayFace - 25.03.2010 14:17

Я просто ставил хук в malloc и запоминал адрес, размер, адрес возврата. Код есть для отдельной dll.


RE: Программирование ВОГ - Дьякон - 25.03.2010 22:21

Хм... спасибо большое, попробую. Довольно логично ))))))))))))))


RE: Программирование ВОГ - etoprostoya - 26.04.2010 00:31

(26.03.2010 02:19)Berserker Wrote:      PLodhead = ^Lodhead;
    TLodStruct = packed record // тип для чтения информации о файле
    NameFile: array[1..16] of char; // Имя файла. 0 в конце обязателен.
    StartSingleFile: Longint; // начало файла в лоде.
    LenSingleFile: Longint; // длина файла вне архива
    Unk1: Longint; // Тип файла
    RealSize: Longint; // размер запакованного файла, 0 если файл не запакован.
    end;
Нашёл такое описание:
Quote:FATRecord: record
    Name: array[1..12]of char; //Имя файла.
    Unknown: array[1..4] of char; //Возможно мусор.

    Offset: LongInt; //Смещение до файла.
    Size: LongInt; //Размер файла.
    Unknown: array[1..4] of char; //Возможно мусор.
    CompressedSize: LongInt; //Сжатый размер файла.
end;
Интересно, значит ли это, что файлы в лоде могут иметь имя длиной до 15 символов (с точкой и расширением), вместо 12 стандартных?


RE: Программирование ВОГ - Berserker - 26.04.2010 00:33

Да.


RE: Программирование ВОГ - baratorch - 26.07.2010 02:13

всем привет.
Сейчас занимаюсь перемещением стеков существ в окне обмена м-ду героями.
добавляю 17 кнопок: кнопку обмена армиями, 2 кнопки передачи армиий от одного героя другому, и под каждым слотом кнопка передачи отряда другому герою.

В связи с этим вопросы: Как узнать уровень существа (не вог-опыта, а существа) зная его тип. Как узнать, грейд/не грейд? Как передать из стека в стек вог-опыт? И по какому принципу вычислять вог-опыт при разделении отрядов и их слиянии?


RE: Программирование ВОГ - Дьякон - 26.07.2010 09:09

По адресу 6747B0 находится указатель на структуру монстров. Структура описана в первом посте инженерного анализа на дф2. Оттуда узнаешь грейд/не грейд и уровень существа. А передачу монстров лучше наверное делать через функцию героев, она автоматом все сама посчитает. ИМХО


RE: Программирование ВОГ - baratorch - 26.07.2010 13:12

спасибо большое!

Quote:
Code:
Town: int;
   Level: int;
   SoundName: PChar; // 4 буквы, с которых начинаются звуки монстра
   DefName: PChar;
   Flags: int;
   Name: PChar;
   PluralName: PChar;
   Features: PChar; // (описание способностей)
   CostWood: int;
   CostMercury: int;
   CostOre: int;
   CostSulfor: int;
   CostCrystal: int;
   CostGems: int;
   CostGold: int;
   FightValue: int;
   AIValue: int;
   Growth: int;
   HordeGrowth: int;
   HitPoints: int;
   Speed: int;
   Attack: int;
   Defence: int;
   DamageLow: int;
   DamageHigh: int;
   Shots: int;
   Spells: int;
   AdvLow: int;  // ?
   AdvHigh: int; // ?
так и не понял как узнать грейд или не грейд монстра...

Quote:А передачу монстров лучше наверное делать через функцию героев, она автоматом все сама посчитает.ИМХО
я реализую умную передачу - то есть монстры передаются по убыванию уровня, если у принимающего уже есть стек с таким типом монстра, то передаваемые добавляются в этот стек, если нет - кидаются в пустой стек. Поэтому мне удобнее непосредственно со стеками работать, а не через функции.


RE: Программирование ВОГ - SAG - 26.07.2010 13:35

(26.07.2010 13:12)baratorch Wrote:  так и не понял как узнать грейд или не грейд монстра...
предполагаю что нет понятия грейд/не грейд. Ручками определяется по номеру монстра.
(26.07.2010 13:12)baratorch Wrote:  я реализую умную передачу
ты посмотрел как эти функции работают в ТЕ/WT? там идеально


RE: Программирование ВОГ - etoprostoya - 26.07.2010 14:14

Должна быть таблица, где описано кто чей грейд.


RE: Программирование ВОГ - Berserker - 26.07.2010 16:59

Есть таблица, Бараторч, инфу скоро вышлю в ЛС.


RE: Программирование ВОГ - baratorch - 27.07.2010 00:59

Berserker, cпасибо большое!

...

никто не скажет чтоли как(где) опыт существ передается и распределяется при разделении/слиянии.
А то я уже всё реализовал, но в вог/эре существа у меня перемещаются, а опыт остается привязанным к слоту.
Так же некорректно с опытом работает реализованное мной перемещение последнего стека героя.

(26.07.2010 13:35)SAG Wrote:  
(26.07.2010 13:12)baratorch Wrote:  я реализую умную передачу
ты посмотрел как эти функции работают в ТЕ/WT? там идеально
какие функции? я опять что-то упускаю? В те/вт можно передать армию от одного героя другому (не обменять, а в одностороннем порядке передать)? как?


RE: Программирование ВОГ - Berserker - 27.07.2010 01:06

baratorch, опыт просто. (КолВоСуществ1 * Опыт1 + КолВоСуществ2 * Опыт2) / (КолВоСуществ1 + КолВоСуществ2). Только нужно юзать двойные int-ы, чтобы переполнения не было.


RE: Программирование ВОГ - GrayFace - 27.07.2010 13:19

(26.04.2010 00:31)etoprostoya Wrote:  Интересно, значит ли это, что файлы в лоде могут иметь имя длиной до 15 символов (с точкой и расширением), вместо 12 стандартных?
Лучше их не использовать. У меня такие файлы читались, но нет полной уверенности.


RE: Программирование ВОГ - SAG - 28.07.2010 11:31

(27.07.2010 00:59)baratorch Wrote:  какие функции? я опять что-то упускаю? В те/вт можно передать армию от одного героя другому (не обменять, а в одностороннем порядке передать)? как?
для удобства, в ТЕ/WT часть операций с армиями не делали кнопками а повесили на клавиши (левые) CTRL, SHIFT , ALT
например:
- для передачи стека целиком от одного героя другому - CTRL+ALT+клик на стек.
CTRL+ALT+SHIFT+клик на стек - разделяет этот стек пропорционально по пустым стекам текущего героя
CTRL+SHIFT+клик на стек - отделяет от стека 1 существо в один пустой стек (единички постоянно требуются в боях для снятия ответного удара)
CTRL+клик на стек - отделяет от стека 1 существо во все пустые стеки
ALT+клик на стек - собирает в кликнутый стек все армии этого типа со всех стеков текущего героя


RE: Программирование ВОГ - Druin - 28.07.2010 12:06

Нету ТЕ под рукой и проверить не могу, но есть уверенность что все эти возможности на ЕРМ реализованы, а не в экзешнике...


RE: Программирование ВОГ - MOP - 28.07.2010 13:33

Да так и есть.
(28.07.2010 11:31)SAG Wrote:  для удобства,
Никогда не понимал, что такого удобного в использовании двух рук вместо одной + требовании держать в голове или бумажке такие извращенские комбинации.


RE: Программирование ВОГ - baratorch - 29.07.2010 09:34

Quote:для удобства, в ТЕ/WT часть операций с армиями не делали кнопками а повесили на клавиши (левые) CTRL, SHIFT , ALT
а вот и не для удобства, а потому что это было самым простым решением.

Quote:(единички постоянно требуются в боях для снятия ответного удара)
Я, между прочим, 9 лет играл в героев, прежде чем начать их модить.

Quote:CTRL+клик на стек - отделяет от стека 1 существо во все пустые стеки
ALT+клик на стек - собирает в кликнутый стек все армии этого типа со всех стеков текущего героя
про эти сочетания я знал, и оценил. Собирался сделать то же самое для сод.

Почему я вообще взялся за управление стеками? Просто я только что, после большого перерыва, поиграл в героев (в СоД есс-но, в другое я не играю) и непосредствеенно почувствовал чего мне не хватает.

Сколько пушей/кликов нужно в те, чтобы передать недельный прирост города от второстепенного героя главному? У меня - 1 клик на кнопку.


RE: Программирование ВОГ - etoprostoya - 29.07.2010 09:54

Есть техническая возможность избавиться от неудобных LOD'ов, заменив их другими архивами, ZIP'ом, например, или свободным gzip?
Было бы просто замечательно! Sm


RE: Программирование ВОГ - vizit0r - 29.07.2010 12:36

(29.07.2010 09:54)etoprostoya Wrote:  Есть техническая возможность избавиться от неудобных LOD'ов, заменив их другими архивами, ZIP'ом, например, или свободным gzip?
Было бы просто замечательно! Sm
напиши на форуме VCMI.
впрочем, думаю что-то в этом духе у них уже в проекте есть, должно быть по логике...


RE: Программирование ВОГ - SAG - 29.07.2010 18:58

(29.07.2010 09:34)baratorch Wrote:  а вот и не для удобства, а потому что это было самым простым решением.
ну кнопку могли сделать, просто она не нажималась бы. некрасиво но не критично. А клавишами в самом деле немного удобнее - потому что быстрее чем мышку передвигать. В мультиплеере счет идет на секунды, т.к. игры занимают много времени.
Quote:Я, между прочим, 9 лет играл в героев, прежде чем начать их модить.
поздравляю. рекомендую сыграть в онлайне с сильными игроками. победить опытного игрока намного сложнее и интереснее чем убивать ограниченного в своих действиях компа.
Quote:про эти сочетания я знал, и оценил. Собирался сделать то же самое для сод.

вопрос будет ли твой сод совместим с обычным содом? проблема совместимости весьма большая. Счас модов располодилось дофига. Аудитория СОД очень консервативна.

(29.07.2010 09:34)baratorch Wrote:  Сколько пушей/кликов нужно в те, чтобы передать недельный прирост города от второстепенного героя главному? У меня - 1 клик на кнопку.
в ТЕ/WT тоже 1 клик на кнопку "Exchange Army". Только в ТЕ можно поставить мой скрипт на фокусировку на правого героя, а в СОД - нет. С фокусировкой передача еще в 1,5 раза быстрее и не отвлекает внимание (при передаче через 5-7 героев не надо вспоминать кому передал, т.к. этот герой автоматически становится активным)
Добавлено:
(28.07.2010 13:33)MOP Wrote:  Никогда не понимал, что такого удобного в использовании двух рук вместо одной + требовании держать в голове или бумажке такие извращенские комбинации.
это не сложнее, чем запомнить например различия 140 героев. руки запоминают моторной памятью за 4-5 игр и потом в СОД постоянно хочется ругаться матом


RE: Программирование ВОГ - baratorch - 30.08.2010 18:58

Давно хочу сделать интегрированную в хайрез поддержку 32битного режима.
И тут вчера случайно отреверсил в героях всё что связано с ddraw.
В связи с этим вопрос:
Дано:
программа использующая ddraw (Герои)
backbuffer ddraw surface c пиксельформатом 16 bit 565
primary ddraw surface c пиксельформатом 32 bit 5555
Есть ли какие нибудь стандартные directx инструменты, чтобы нарисовать на этом primary содержимое этого backbuffer? Или нужно писать что-то свое, медленное.
Я так понимаю Блиттинг возможен только между поверхностями одного формата? Или нет?
В directx я не очень шарю, просто в детстве немного почитал MSDN Lib. )

На каком, интересно, принципе основана работа 32bit патча?..

И еще вопрос: В IDirectDraw и IDirectDrawSurface первых версий (которые используются в героях) нет возможности применить сглаживание при блиттинге с изменением масштаба? В каких есть? Хотелось бы сделать в героях проигрывание растянутого видео с интерполяцией


RE: Программирование ВОГ - gamecreator - 30.08.2010 19:28

(30.08.2010 18:58)baratorch Wrote:  На каком, интересно, принципе основана работа 32bit патча?..
емнип, там заменяется библиотека ddraw


RE: Программирование ВОГ - GrayFace - 31.08.2010 22:25

Да, потом создаются свои прокси IDirectDraw, IDirectDrawSurface и т.п., которые перекидывают с 16-битной поверхности на 32-битную. Блиттинг используется через канвасы (HDC) поверхностей, т.к. другие варианты работали не у всех.
Bourn уже сделал поддержку нового DirectX - с нормальным сглаживанием и другими интересностями. Лучше всего тебе поговорить с ним.


RE: Программирование ВОГ - baratorch - 03.09.2010 00:52

(31.08.2010 22:25)GrayFace Wrote:  Да, потом создаются свои прокси IDirectDraw, IDirectDrawSurface и т.п., которые перекидывают с 16-битной поверхности на 32-битную.
Впринципе я это знал, я поковырял немного zdraw.dll, но для полного понимания решения чего то не хватало. Твой пост, sergroj, переключил в моей голове нужный триггер, спасибо!

(31.08.2010 22:25)GrayFace Wrote:  Блиттинг используется через канвасы (HDC) поверхностей
Что это и как это, я не представляю. Сделал собственные функции конвертации из 16-битн. поверхности в 32 и обратно. Функции довольно грубые но шустрые. Неточность вычислений на глаз незаметна, и тормозов никаких на моем нетбуке нет.
Всего три сдвига и два AND'a на пиксель на конвертацию туда
   и три сдвига плюс два OR'а на конвертацию обратно. Никаких умножений и делений.

Однако, при размере окна близком к размеру экрана в моем патче у меня проявился абсолютно такой же глюк, что и в последней лучшей zdraw.dll.
Очевидно он появляется при блиттинге между 16 битными поверхностями при 32-битном режиме.
Т.е. свою задачу я не решил..
   Попробую заменить и 16-битные директдро поверхности и функцию блиттинга своими структурами и кодом, посмотрим решит ли это проблему...


RE: Программирование ВОГ - totkotoriy - 18.02.2012 13:50

Господа-товарищи помогите пожалуйста написать плагин в GCC:
Code:
#include <windows.h>
#include <stdio.h>
#include <setjmp.h>
#include <map>
using std::map;

#define OPCODE_JUMP 0xE9
#define OPCODE_CALL 0xE8
#define OPCODE_NOP 0x90

#define HOOKTYPE_JUMP 0
#define HOOKTYPE_CALL 1

#define HOOK_SIZE 5

inline void WriteHook( void *pOriginal, void *pNew, char type )
{
    *(byte*)pOriginal = (type==HOOKTYPE_JUMP)?OPCODE_JUMP:OPCODE_CALL;
    *(void**)( (byte*)pOriginal + 1 ) = (void*)( (byte*)pNew - (byte*)pOriginal - HOOK_SIZE );
}



__fastcall void FirstChange()
{
__asm
{
   pushad
   push   TriggerNum
   mov    eax, 0x74CE30
   call   eax              
   add    esp, 4              
   popad                    
}
}


extern "C" __stdcall BOOL DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{

    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
              {
                  WriteHook((void*)0x4074AC, (void*)(FirstChange), HOOKTYPE_CALL);
                break;
              }

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
}
В общим нужен хук по адресу 4074AC
и сделать чтоб по нему можно из ERM вызвать триггер.
Выдает всяческие ошибки в функции ASM - что-то я не правильно написал.
И ещё - какой номер триггера вставить вместо TriggerNum? Как я понимаю не занятый триггер WOG в шестнадцатеричном виде?


RE: Программирование ВОГ - etoprostoya - 18.02.2012 14:29

В GCC совсем другой ассемблер. http://ru.wikipedia.org/wiki/GNU_Assembler


RE: Программирование ВОГ - totkotoriy - 18.02.2012 16:27

(18.02.2012 14:29)etoprostoya Wrote:  В GCC совсем другой ассемблер. http://ru.wikipedia.org/wiki/GNU_Assembler
Точно, оказывается это код TASM, а для GCC нужен AT&T
так что вот так работает:
Code:
asm
(
    ".intel_syntax noprefix\n" // use intel syntax
    "   pushad                     \n"
    "   push   0x0069DC            \n"
    "   mov    eax, 0x74CE30       \n"
    "   call   eax                 \n"
    "   add    esp, 4              \n"
    "   popad                      \n"
    ".att_syntax noprefix\n"
);



RE: Программирование ВОГ - kostya_76 - 18.02.2012 19:14

(18.02.2012 16:27)totkotoriy Wrote:  А может есть у кого-нибудь готовый код для C++ на создание нового триггера? А то че-то теперь в героях ошибки полезли Bad

Вот пример на паскале:
Обработчик хука на ассемблере. Перенести в С++ легко, если сам хук сможешь создать. В теме " Исследование героев" раздела "Моды" есть еще более подробный комментарий, если комментария в тексте недостаточно.


RE: Программирование ВОГ - Sav - 18.02.2012 20:52

А функция FireEvent в Эре случайно не запускает триггер?


RE: Программирование ВОГ - totkotoriy - 19.02.2012 13:23

(18.02.2012 19:14)kostya_76 Wrote:  Обработчик хука на ассемблере. Перенести в С++ легко, если сам хук сможешь создать. В теме " Исследование героев" раздела "Моды" есть еще более подробный комментарий, если комментария в тексте недостаточно.
Перенести то легко, но мне нужен немного другой код асма и как его правильно написать я не знаю.


RE: Программирование ВОГ - MOP - 20.02.2012 07:54

Ладно, вброшу сюда свой low-level бред для начинающих.

Простейшая stdcall-ная функция установки хука на асме имеет вид:
Code:
mov eax, [esp + 0x0C]
lea eax, [eax + 0xE8]
mov ecx, [esp + 8]
mov edx, [esp + 4]
mov [edx], al
lea eax, [edx + 5]
sub ecx, eax
mov [edx + 1], ecx
ret 0xC
3 параметра: адрес для помещения хука, адрес dll-процедуры, тип хука (0 - call, 1 - jump).

Некоторые люди ещё юзают VirtualProtect до и после установки хука, но в Воге это не нужно.
Ещё бывает, что остаток изменённого кода затирают nop-ами, но мне лично это ни разу не понадобилось: call-ом обычно замещается тоже вызов функции, так что длина опкода остаётся той же, а jump позволяет всё равно прыгать после возврата на корректный адрес. Вообще, куда и как ставить хук - отдельная история, но сам стараюсь ставить так, чтобы он менял только 5 байт.

Ещё более минималистская форма (без процедуры) массовой установки хуков - из Drew.dll:
Code:
...
    mov esi, offset Hook_Table
LoopHooks:
    mov al, [esi+8]
    mov ecx, [esi+4]
    mov edx, [esi]
    mov [edx], al
    lea eax, [edx+5]
    sub ecx, eax
    mov [edx+1], ecx
    add esi, 9
    cmp esi, End_Hook_Table
    jl LoopHooks
    ...
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
TJump equ 0E9h
TCall equ 0E8h

Hook MACRO ExeAdress, ProcDrew, TypeHook
    dd ExeAdress
    dd ProcDrew
    db TypeHook
ENDM

Hook_Table:
; 1. ДИАЛОГ СТАРТОВЫХ ХАРАКТЕРИСТИК ГЕРОЯ
    Hook 569DECh, StartHeroDialog, TCall
    Hook 5826ACh, StartHeroDialog, TCall
    Hook 5828C6h, StartHeroDialog, TCall
; 2. ОПЦИЯ ЗАПРЕТА ОТОБРАЖЕНИЯ ЭКРАНА ЗАГРУЗКИ КАРТЫ
    Hook 4ED9E0h, change_LoadScreen, TJump
    Hook 4EF83Ch, change_LoadScreen1, TJump
; 3. ВСТАВКА ТЕКСТА ИЗ БУФЕРА ОБМЕНА
    Hook 5BB500h, MainKeyboard, TJump
; 4. ИМЕНА ИГРОКОВ ДЛЯ ХОТ-СИТА
    Hook 51231Fh, MultiPlayerButtons, TJump
    Hook 512221h, MultiPlayerload_file_10_mop, TJump
    Hook 512276h, MultiPlayerStrings_realize, TJump
    Hook 512696h, MultiPlayerDialogresult, TJump
    Hook 50E229h, MultiPlayerInterdiction, TJump
; 5. УВЕЛИЧЕНИЕ КОЛИЧЕСТВА ЗАКЛИНАНИЙ В ИГРЕ
    Hook 59CD5Bh, SpellsExpand1, TJump
    Hook 4D8F77h, SpellsExpand2, TJump
    Hook 4D8B6Ah, SpellsExpand3, TJump
    Hook 4D95A8h, SpellsExpand4, TJump
End_Hook_Table:



RE: Программирование ВОГ - Berserker - 20.02.2012 18:56

Nop-ы не дают процессору подавиться на неправильных командах (сброс кеша, остановка предсказания переходов), идущей за перехватом, а также сохраняют отладчик от нервной дрожи при анализе.


RE: Программирование ВОГ - MOP - 20.02.2012 19:08

Это понятно, я же приводил минималистскую форму. А если место для хука подбирать очень тщательно, то остатков кода может вообще не быть.


RE: Программирование ВОГ - Berserker - 20.02.2012 20:02

Как у тебя с FASM-ом, стабильность выросла по сравнению с ЕРМ или упала?


RE: Программирование ВОГ - MOP - 21.02.2012 12:12

Ну пока вроде всё стабильно. Работаю в режиме DisableERM=TRUE. Если какие-то ошибки происходят, то только по моей вине, как всегда. Тщательно слежу за тем, что компилируется.
Что-то делать на нормальном языке проще, чем на ERM, а что-то сложнее. Пока сопротивления особого не встречаю, но боюсь работы с опытом существ. Это такая муть... Причём исходники ВОГ-а тут ничем не помогут, ибо там муть ещё похуже, чем разобрать работу ERM-команды.
FASM доставляет тем, что практически безглючен и крайне прост. Никаких offset-ов и страшных dword ptr ds. Не ругается почём зря, как MASM. Кое-чего из MASM-а, конечно, не хватает, но плюсов нахожу больше.