#pragma once

#ifdef __cplusplus
//#include "../include/targetver.h"
#include "obfuscation/MetaRandom2.h"
#endif

//
// Инструменты для придания коду полиморфности (чтобы один и тот же кусок кода при компиляции
// производил разные последовательности инструкций, и нельзя было выделить сигнатуру участка кода).
// Использовать так:
//
// foo();            // что-то полезное
// 
// morphcode();      // полиморфная вставка 
//
// int a = bar();    // что-то полезное
//
// morphcode(a);     // полиморфная вставка, использующая результаты предыдущего действия
//



#if defined(MORPHCODE)

#define morphcode()
#define morphcode(a)

#else



// полиморфная рандомная вставка в код, для рандомизации сигнатур
#ifdef __cplusplus
__forceinline void morphcode(int a) {
#else
__forceinline void morphcode(char* a) {
#endif
#ifdef __cplusplus
	volatile int _morph_var = static_cast<int>(1 + MetaRandom2<0, 0x7FFFFF - 1>::value);
#else
	volatile int _morph_var = a;
#endif

	// делаем арифметическую операцию со случайным (времени компиляции) числом, и операндом.
	// за счет того, что число известно во время компиляции, оптимизатор оставит лишь один вариант действия,
	// выкинув остальные. Таким образом, одна и та же вставка будет давать всякий раз разный результат.
	if (_morph_var % 3) {
		_morph_var += (int)a + 2;
		while (!(_morph_var % 4)) ++_morph_var;
	}
	else if (_morph_var % 2) {
		_morph_var -= (int)a - 2;
		while (!(_morph_var % 3)) ++_morph_var;
	}
	else if (_morph_var % 4) {
		_morph_var = (_morph_var + 2) * ((int)a + 3);
		while (!(_morph_var % 2))
			if (_morph_var % 5)
				--_morph_var;
			else ++_morph_var;
	}
	else if (_morph_var % 5) {
		_morph_var = (_morph_var + 11) / ((int)a + 23);
		while (!(_morph_var % 3))
			if (_morph_var % 5)
				++_morph_var;
			else --_morph_var;
	}
}

// полиморфная рандомная вставка в код, для рандомизации сигнатур
#ifdef __cplusplus
__forceinline void morphcode(void* a) {
	morphcode((int)a);
}
#endif

// полиморфная рандомная вставка в код, для рандомизации сигнатур
#ifdef __cplusplus
__forceinline void morphcode(void) {
	// присваивание случайного числа

	volatile int _morph_var = static_cast<int>(1 + MetaRandom2<0, 0x7FFFFF - 1>::value);
}
#endif

#endif