Во многом, из исследовательского интереса, мне хочется сделать реализацию некоторых важных функций, которые на мемхаке работают излишне медленно или просто ужасно, внутри кастомной dll, которая будет подгружаться по ходу игры с помощью мемхака.
При этом, мне не до конца понятно, как реализованные в такой dll функции я смогу использовать в своем коде на jass, избегая непростительно медленного использования call функций из мемхака.
Пример:
есть функция мемхака
function ReadRealMemory takes integer address returns integer
Она довольно сложна и тяжела. Хочу себе такую же, но работающую в рамках моей кастомной dll.
Еще мне малосимпотично реализовывать хуки на мемхаке.
И вопрос, как же все-таки получить эти нативки для удобного использования?
Я просмотрел ресурс IceFog по этой теме, но там все настолько засекречено, что я не могу перестать бояться за сохранность куков у моих игроков, кроме того мне не хочется совершать кучу не слишком простых действий с картой после каждого сохранения.

Принятый ответ

goodlyhero, ну уже вроде делали с перехватом кастом функций или хештаблицу, wenhao же видел? Там китайская сборка мемхака и 4 библиотеки.

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

Простые R\W функции то можно не трогать, там все норм. А вот конверты, хуки, вызовы из game.dll - это вот как раз требует нативного решения, ибо довольно медленное.

Ну и думаю ивенты без норм декларации нативок для триггеров не добавить...
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
19
3 года назад
0
0
32
3 года назад
0
Ну тебе нужно задекларировать нативку и в своем коде сделать, заготовку,
native function RMem takes integer returns integer
Ну и подготовить код. Сам RMем то вполне быстрый, долгие - конверты адрессов и хендлов. всякие stdCall, CallFast функции, которые запускают функции внутри гейм длл или другой библиотеке из жасс кода, вот они реально упорото медленные. По этой причине сложные фишки с фреймами на мемхаке такие тормознутые, там перманентный вызов кучи функций из гейм длл.
Само же чтение и запись в память сравнительно быстрое, да не шибко фаст, все же это не нативки, но добится ими проблем (если вы не придурок, который хочет выстрелить себе в ногу) вроде подвисания потока или проблем с производительностью в реальном коде нельзя, в отличии от выше упомянутых функций.
0
8
3 года назад
0
Ну тебе нужно задекларировать нативку и в своем коде сделать, заготовку,
При наличии такого объявления, варкрафт начинает злобно ругаться и валиться с примерно таким текстом:
unregistered native function on line 553 (war3map.j)
Получается, если я хочу использовать эти функции в war3map.j, я должен их каким-то образом загрузить заранее?
0
32
3 года назад
0
goodlyhero, ну как в либе IceFog'а, либо лаунчер как у айкапа. Хотя можно взять левую ИИ нативку, взять её адресс и назначить ей твои дейсвия. К примеру Rmem.
0
8
3 года назад
0
ну как в либе IceFog'а, либо лаунчер как у айкапа. Хотя можно взять левую ИИ нативку, взять её адресс и назначить ей твои дейсвия. К примеру Rmem.
Печально, но я недавно придумал Уууууу костыль, использовать мне его не очень нравится, но можно создать jass функцию с названием, совпадающим с названием нативки и подменить в функции её вызывающей вызов обычной функции на вызов нативки, которую мы предварительно зарегистрировали. Из плюсов - нативку не надо объявлять, из минусов - их добавления ужасно.
Загруженные файлы
1
32
3 года назад
1
goodlyhero, ну уже вроде делали с перехватом кастом функций или хештаблицу, wenhao же видел? Там китайская сборка мемхака и 4 библиотеки.

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

Простые R\W функции то можно не трогать, там все норм. А вот конверты, хуки, вызовы из game.dll - это вот как раз требует нативного решения, ибо довольно медленное.

Ну и думаю ивенты без норм декларации нативок для триггеров не добавить...
Загруженные файлы
Принятый ответ
0
8
3 года назад
0
Ну и думаю ивенты без норм декларации нативок для триггеров не добавить...
Прикрепленные файлы
Прикольно, пусть и непонятно. Нужно будет потыкаться. Спасибо за помощь!...
А по поводу ивентов я мало что понимаю, к несчастию.
0
32
3 года назад
0
goodlyhero, ну чтобы отказатся от хуков - нужны ивенты, а это сложно...
1
19
3 года назад
Отредактирован Ev3nt
1
goodlyhero:
Получается, если я хочу использовать эти функции в war3map.j, я должен их каким-то образом загрузить заранее?
Всё верно. Можно их прописать вверху war3map.j (как делал ENAleksey в картах RenderEdge), в common.j (как делают китайцы, сам иногда также делаю), хукнуть метод выделения памяти варика, когда выделяется память под файлы скриптов, увеличить её на N количество символов, куда потом вы добавите свои обьявления (чтобы не обьявлять их в common.j явно), ну и последний вариант. В варике все скрипты преобразуются в коды операций, каждая из которых состоит из 8 байт, первые 4 являются самой операцией, а оставшиеся 4 - это значение. Таким образом вы можете как создать свой триггер, так и обьявить функцию.
Вот вам типы данных и структуры, которые пригодятся, если вы воспользуетесь последним способом:
Код
enum OPCODES
{
	OPTYPE_MINLIMIT = 0x00,
	OPTYPE_ENDPROGRAM = 0x01,
	OPTYPE_OLDJUMP = 0x02,
	OPTYPE_FUNCTION = 0x03,
	OPTYPE_ENDFUNCTION = 0x04,
	OPTYPE_LOCAL = 0x05,
	OPTYPE_GLOBAL = 0x06,
	OPTYPE_CONSTANT = 0x07,
	OPTYPE_FUNCARG = 0x08,
	OPTYPE_EXTENDS = 0x09,
	OPTYPE_TYPE = 0x0A,
	OPTYPE_POPN = 0x0B,
	OPTYPE_MOVRLITERAL = 0x0C,
	OPTYPE_MOVRR = 0x0D,
	OPTYPE_MOVRV = 0x0E,
	OPTYPE_MOVRCODE = 0x0F,
	OPTYPE_MOVRA = 0x10,
	OPTYPE_MOVVR = 0x11,
	OPTYPE_MOVAR = 0x12,
	OPTYPE_PUSH = 0x13,
	OPTYPE_POP = 0x14,
	OPTYPE_CALLNATIVE = 0x15,
	OPTYPE_CALLJASS = 0x16,
	OPTYPE_I2R = 0x17,
	OPTYPE_AND = 0x18,
	OPTYPE_OR = 0x19,
	OPTYPE_EQUAL = 0x1A,
	OPTYPE_NOTEQUAL = 0x1B,
	OPTYPE_LESSEREQUAL = 0x1C,
	OPTYPE_GREATEREQUAL = 0x1D,
	OPTYPE_LESSER = 0x1E,
	OPTYPE_GREATER = 0x1F,
	OPTYPE_ADD = 0x20,
	OPTYPE_SUB = 0x21,
	OPTYPE_MUL = 0x22,
	OPTYPE_DIV = 0x23,
	OPTYPE_MOD = 0x24,
	OPTYPE_NEGATE = 0x25,
	OPTYPE_NOT = 0x26,
	OPTYPE_RETURN = 0x27,
	OPTYPE_LABEL = 0x28,
	OPTYPE_JUMPIFTRUE = 0x29,
	OPTYPE_JUMPIFFALSE = 0x2A,
	OPTYPE_JUMP = 0x2B,
	OPTYPE_MAXLIMIT = 0x2C
	// OPTYPE_STARTLUATHREAD = 0x2D
};

enum OPCODE_VARIABLE_TYPE
{
	OPCODE_VARIABLE_NOTHING = 0,
	OPCODE_VARIABLE_UNKNOWN,
	OPCODE_VARIABLE_NULL,
	OPCODE_VARIABLE_CODE,
	OPCODE_VARIABLE_INTEGER,
	OPCODE_VARIABLE_REAL,
	OPCODE_VARIABLE_STRING,
	OPCODE_VARIABLE_HANDLE,
	OPCODE_VARIABLE_BOOLEAN,
	OPCODE_VARIABLE_INTEGER_ARRAY,
	OPCODE_VARIABLE_REAL_ARRAY,
	OPCODE_VARIABLE_STRING_ARRAY,
	OPCODE_VARIABLE_HANDLE_ARRAY,
	OPCODE_VARIABLE_BOOLEAN_ARRAY
};

typedef struct
{
	DWORD unk;
	DWORD max_size;
	DWORD array;

	UINT32 get(DWORD index)
	{
		DWORD result = 0;
		if (index < max_size)
		{
			result = array + 0x10 * index;
			++* (UINT32*)(result + 0xC);
		}

		return result;
	}

} STRING_TABLE, * PSTRING_TABLE;

typedef struct {
	BYTE unk[8];
	DWORD table;
} CODE_TABLE, * PCODE_TABLE;

typedef struct {
	BYTE rettype;
	BYTE type;
	BYTE reg;
	BYTE opcode;
	DWORD value;
} JASS_OPCODE, * PJASS_OPCODE;

typedef struct
{
	BYTE unk0[0x20];
	PJASS_OPCODE opcode;
	BYTE unk1[0x10];
	UINT has_sleep;
	BYTE unk2[0x2818];
	DWORD index;
	BYTE unk3[0x20];
	PSTRING_TABLE string_table;
	BYTE unk4[0x10];
	PCODE_TABLE code_table;
	BYTE unk5[0x1C];
} JASS_INSTANCE, * PJASS_INSTANCE;

typedef struct {
	DWORD unk;
	DWORD zero1;
	DWORD zero2;
	DWORD zero3;
	DWORD zero4;
	DWORD zero5;
	DWORD type1;
	DWORD type2;
	DWORD value;
	DWORD zero6;

	void set(DWORD value, OPCODE_VARIABLE_TYPE type)
	{
		this->value = value;
		type1 = type;
		type2 = type;
	}

} JASS_DATA_SLOT, * PJASS_DATA_SLOT;

typedef struct {
private:
	DWORD unk1;
	DWORD unk2;
	size_t stack_top; // Idk why it's here
	PJASS_DATA_SLOT stack[32];
	size_t size;
public:
	PJASS_DATA_SLOT pop()
	{
		return stack[--size];
	}

	PJASS_DATA_SLOT& operator[](size_t index)
	{
		return stack[index];
	}

	void clear(size_t number)
	{
		size = number < size ? size - number : 0;
	}

	size_t Size()
	{
		return size;
	}
} JASS_STACK, * PJASS_STACK;

typedef struct {
private:
	std::vector<JASS_OPCODE> oplist;
public:
	void addop(BYTE opcode, BYTE reg = 0, DWORD value = NULL, BYTE type = OPCODE_VARIABLE_NOTHING, BYTE rettype = OPCODE_VARIABLE_NOTHING)
	{
		JASS_OPCODE* _opcode = new JASS_OPCODE;
		_opcode->rettype = rettype;
		_opcode->type = type;
		_opcode->reg = reg;
		_opcode->opcode = opcode;
		_opcode->value = value;

		oplist.push_back(*_opcode);
	}

	DWORD getcode()
	{
		return ((DWORD)&oplist - GetJassMachine()->code_table->table) / 4;
	}

} JASS_OPLIST, * PJASS_OPLIST;
Чтобы оставить комментарий, пожалуйста, войдите на сайт.