#define introcodesize 27
#define writecodesize 21
#define closecodesize 12
#define skippersize 225
#define skippercoresize 8
_u8 initdummy[0x1d]={0x06,0x0e,0x07,0x33,0xc9,0x8c,0xc3,0x8b,0xf1,0x4e,0x89,0xf7,0x8e,0xdb,0x2b,0x1e,0x0a,0x00,0x8e,0xdb,0xfd,0x8c,0xc3,0x90,0xb8,0x2b,0x00,0x90,0x90};
_u8 fileiniter[introcodesize]={0x90,0x5B,0x83,0xC3,0x10,0x8E,0xC3,0x1e,0xb8,0x02,0x3d,0x8C,0xCB,0xB1,0xFF,0xBA,00,00,0x8e,0xDB,0xCD,0x21,0x1F,0x89,0xC3,0x53,0x1e};
_u16 introcode_offset=16;
_u8 filewriter[writecodesize]={0xb8,0x00,0x40,0xb9,00,00,0x53,0x8c,0xc3,0x81,0xc3,00,00,0xBA,00,00,0x8e,0xDB,0x5B,0xCD,0x21};
_u16 writecode_offset1=4;
_u16 writecode_offset2=11;
_u8 filecloser[closecodesize]={0x1F,0x5B,0xB8,0x00,0x3E,0xCD,0x21,0xB8,0x00,0x4C,0xCD,0x21};
_u8 skippercore[skippercoresize]={0x58,0x50,0x05,0x10,0x00,0x8E,0xC0,0xFC};
_u16 blocksize=0xFFF0;

_u16 modifymode;
typedef _u8 memblock_[65535];

_u8 codecur;
_u16 codeword;
_u16 counter;
int ibeenden;
_u8 currentcodon;
_i32 ilv1;
_u8 hv1;
_u16 whv1;
_u8 transferrednumber;
_u16 memblocklooper;
_u16 currentdistance;
memblock_ olddata;
_u16 relomode;
_u16 relocount;

FILE*infile;
FILE*outfile;
_u16 blockcount;
_u16 addiblock;
_u8*extraname;
_u8*targetname;
_i32 relotable_block;
_i16 relotable_kitt;
typedef struct
{
		int headersize;
		int basic;
		int relotab;
		int entrypnt;
		int jumppoint;
		int exesize;
		int absauxsize;
		int expansion;
		int contentsize;
		int stacksegment;
		_u16 trueentry_offset;
		_u16 trueentry_segment;
		_u16 truestack_offset;
		_u16 truestack_segment;
}exeinfo;
exeinfo inattr,outattr,saverattr;

_u8 ihv1;

_u16 pow2(_u8 eingabe)
{
	return 1<<eingabe;
}

_u16 inword()
{
	_u16 backval=0;
	fread(&backval,2,1,infile);
	return backval;
}

_u8 inbyte()
{
	_u8 backval=0;
	fread(&backval,1,1,infile);
	return backval;
}

void outbyte(_u8 ihv1)
{
	fwrite(&ihv1,1,1,outfile);
	olddata[memblocklooper]=ihv1;
	memblocklooper++;
	if (memblocklooper==65535) memblocklooper=0;
}

_u8 loopback(_u16 amount)
{
	_u16 zielpos=memblocklooper+amount;
	if (zielpos>=memblocklooper)
	{
		zielpos-=1;
	}
	return olddata[zielpos];
}

_u8 takebit()
{
	int retval;
	if ((codeword & pow2(16-codecur))>0)
	{
		retval=1;
	}
	else
	{
		retval=0;
	}
	codecur--;
	if (codecur==0)
	{
		codeword=inword();
		codecur=16;
	}
	return retval;
}

_u16 getword(int pos)
{
	_u16 backval;
	fseek(infile,pos,SEEK_SET);
	fread(&backval,2,1,infile);
	return backval;
}

void putword(int pos,_u16 output)
{
	fseek(outfile,pos,SEEK_SET);
	fwrite(&output,2,1,outfile);
}

void outlong(_u32 output)
{
	fwrite(&output,4,1,outfile);
}

void outword(_u16 output)
{
	fwrite(&output,2,1,outfile);
}

void unpack()
{
	int ilv1;
	for (ilv1=0;ilv1<counter;ilv1++)
	{
		outbyte(loopback(currentdistance));
	}
}
void innercode()
{
	_i32 ilv1;
	for (ilv1=0;ilv1<65535;ilv1++)
		olddata[ilv1]=0;
	codecur=16;
	codeword=inword();
	memblocklooper=0;
	ibeenden=0;
	do
	{
		currentcodon=takebit();
		if (currentcodon==1)
		{
			outbyte(inbyte());
		}
		else
		{
			currentcodon=takebit();
			if (currentcodon==0)
			{
				counter=2;
				currentcodon=takebit();
				counter=counter+currentcodon*2;
				currentcodon=takebit();
				counter=counter+currentcodon;
				currentdistance=inbyte()+0xFF00;
				unpack();
			}
			else
			{
				whv1=inword();
				counter=(whv1/256) & 7;
				currentdistance=(whv1/2048)*256+(whv1 & 255)+0xE000;
				if (counter==0)
				{
					hv1=inbyte();
					switch (hv1)
					{
						case 0:
						{
							ibeenden=1;
							break;
						}
						case 1:
						{
							//printf('Segmentwechsel\n');
							break;
						}
						default:
						{
							counter=hv1;
							counter=counter+1;
							unpack();
							break;
						}
					}
				}
				else
				{
					counter=counter+2;
					unpack();
				}
			}
		}
	}
	while (ibeenden==0);
}

void getrelo()
{
	_u8 ihv1,ihv3;
	_u16 ihv2;
	_i32 icurrentpos;
	_u16 icurrentpos1,icurrentpos2;
	int ibeenden=0;
	fseek(infile,inattr.relotab,SEEK_SET);
	icurrentpos=0;
	do
	{
		fread(&ihv1,1,1,infile);
		if (ihv1==0)
		{
			fread(&ihv2,2,1,infile);
			if (ihv2==0)
			{
				icurrentpos=icurrentpos+0xFFF0;
				printf("Sprung\n");
			}
			if (ihv2==1)
			{
				ibeenden=1;
			}
			else //was ist mit ihv2>32767? ich denke, es ist ein word...
			{
				icurrentpos=icurrentpos+ihv2;
			}
		}
		else
			icurrentpos=icurrentpos+ihv1;
		if (ibeenden==0)
		{
			relocount++;
			icurrentpos1=icurrentpos % 16;
			icurrentpos2=icurrentpos / 16;
			outword(icurrentpos1);
			outword(icurrentpos2);
			printf("%i\n",icurrentpos);
		}
	}
	while (ibeenden==0);
}
