byte Decompressor1Exe=FROM "lzssexe.bin";
byte Decompressor1Dll=FROM "lzssdll.bin";

struct UCHEADER{
	dword uSrc;	//адрес начала секции сжатых данных
	dword	OldImp;	//importRVA исходного файла
	dword	MyIBase;	//ImageBase исходного и выходного один и тот же ???
	dword	OldEnt;	//EntryRVA исХодного файла
	dword JumpRVA;
	dword JumpNum;	//число модернизированых E8
	dword ReloOld;
	dword SPos;
	dword ReloLen;
};

dword RealLenFix;
dword RealDC;	//размер заголовка декомпресора
dword RealLen;	//полный размер декомпресора в выходном файле без заголовка
dword DeLen;    //длина кода декомпресора без таблицы импорта
dword DImport;	//RVA таблицы импорта декомпрессора
static dword ImportDc;	//Адрес импорта
static dword FixUpDc;   //адрес таблицы перемецения
static dword FixUpEnd;  //конец таблицы перемещения
dword DcRVA;	//исходный RVA секции декомпресора

void fastcall InitDecompressor(EBX);
void fastcall RelocateDC(EDI);

void fastcall InitDecompressor(EBX)
{
	$push EBX
	SWITCH(cfgpack.CompressionType){
		CASE 0:
		CASE 1:
			IF(DSDWORD[EBX+#PE_HEADER.exportRVA]==0){
				ECX=sizeof(UCHEADER)-12;
				EAX=#Decompressor1Exe;
			}
			ELSE{
				ECX=sizeof(UCHEADER);
				EAX=#Decompressor1Dll;
			}
			BREAK;
	}
	RealDC=ECX;	//размер таблицы декомпресора
	ECX=EAX;	//адрес декомпрессора
	$push EAX
	ECX+=DSDWORD[ECX+0x3C];	//начало PE заголовка
	EBX=ECX;
	EBX+=sizeof(PE_HEADER);	//начало таблицы объектов
	EDX=DSDWORD[EBX+#OBJECT_ENTRY.pOffset];	//смещение секции в файле
	EDI=DSDWORD[EBX+#OBJECT_ENTRY.sectionRVA];
	DcRVA=EDI;
	RealLen=DSDWORD[ECX+#PE_HEADER.fixupRVA]-EDI-RealDC;
	RealLenFix=EAX+DSDWORD[ECX+#PE_HEADER.fixupSize];
	DeLen=DSDWORD[ECX+#PE_HEADER.importRVA]-EDI-RealDC;
	DImport=DSDWORD[ECX+#PE_HEADER.importRVA];
	ImportDc=EAX-EDI;
	FixUpDc=DSDWORD[ECX+#PE_HEADER.fixupRVA]-EDI;
	FixUpEnd=EAX+DSDWORD[ECX+#PE_HEADER.fixupSize];
	pe_head.importSize=DSDWORD[ECX+#PE_HEADER.importSize];
	pe_head.fixupSize=DSDWORD[ECX+#PE_HEADER.fixupSize];
	$pop EAX
	CurDc=EAX+EDX;	//адрес секции декомпресора
	ImportDc+=EAX;
	FixUpDc+=EAX;
	FixUpEnd+=EAX;
	$pop EBX
}

void fastcall RelocateDC(EDI)
{
	ESI=ImportDc;
	for(;;ESI+=0x14){
		IF(DSDWORD[ESI]==0){
			IF(DSDWORD[ESI+0x10]==0)BREAK;
		}
		ELSE{
			EAX=CurDc+DSDWORD[ESI]-DcRVA;
			DSDWORD[ESI]+=EDI;
			ESI><EAX;
			WHILE(DSDWORD[ESI]){
				DSDWORD[ESI]+=EDI;
				ESI+=4;
			}
			ESI><EAX;
		}
		DSDWORD[ESI+12]+=EDI;
		EAX=CurDc+DSDWORD[ESI+16]-DcRVA;
		DSDWORD[ESI+16]+=EDI;
		ESI><EAX;
		WHILE(DSDWORD[ESI]){
			DSDWORD[ESI]+=EDI;
			ESI+=4;
		}
		ESI><EAX;
	}
	ESI=FixUpDc;
	EDI+=pe_head.ImageBase;
 	do{
 		$lodsd
		IF(EAX==0)BREAK;;
		EAX=EAX-DcRVA+CurDc;
		EAX><EDX;
		$lodsd
		EAX=EAX-8>>1;
		EAX><ECX;
		EAX=0;
		LOOPNZ(ECX){
			$lodsw
			EAX&=0xFFF;
			IF(EAX>=RealDC)DSDWORD[EDX+EAX]+=EDI;
		}
	}while(ESI<FixUpEnd);
}

//?define	ReloPos		68
