// ****************************************** Globale Typen  //  Variablen
// ****************************************** Globale Typen  //  Variablen
// ****************************************** Globale Typen  //  Variablen
// ****************************************** Globale Typen  //  Variablen

typedef char paltype[768];

// Coordedspritetype
class coordedspritetype{
public:
    int16 posx,posy;
    uchar spritenummer;
    uchar gesehen;
};
machezeigerelemtype(coordedsprite);


// Screens
spritetype *virtualvga;
spritetype *realvga;









// ************************************************* Externe Routinen
// ************************************************* Externe Routinen
// ************************************************* Externe Routinen
// ************************************************* Externe Routinen
// ************************************************* Externe Routinen
// ************************************************* Externe Routinen
// ************************************************* Externe Routinen

//ende der bearbeitung am 11.8.95
/*
extern"C"{
	//uint cdecl kompasm(ulong anzbytes,void *dest,void *source);
	//void cdecl entkompasm(ulong anzbytes,void *dest,void *source);
	//void cdecl showpal(paltype pal);
	//void cdecl copyvga();
	//void cdecl pixel(spritetype *dest,int x,int y,char color);


	//void cdecl putsprite_clipcoord_transparent(spritetype *dest,int x,int y,
	//	spritetype *source);
	void cdecl putsprite__clipcoord(spritetype *dest,spritetype *source,int x,int y);
	void cdecl putsprite_clipcoord_(spritetype *dest,int x,int y,spritetype *source);
	void hline_clip(spritetype *dest,int x1,int x2,int y,char farbe);  // OUL => OUR
	void lineintern(char *dest, int x1,int y1,int x2,int y2,int breitex,char farbe);
};
*/






// **************************************************** VGA - Initialisierung
// **************************************************** VGA - Initialisierung
// **************************************************** VGA - Initialisierung
// **************************************************** VGA - Initialisierung
// **************************************************** VGA - Initialisierung
// **************************************************** VGA - Initialisierung

void initvga()
{
    	// VgaMode initen
	vga_setmode(VGAMODE);
	gl_setcontextvga(VGAMODE);

	sprite_linear_nontransparenttype virtualvga(256,200,128,100);
	sprite_linear_nontransparenttype realvga(320,200,0,0);
};


void deinitvga()
{
    vga_setmode(TEXT);
};







// ****************************************************** Palette ********
// ****************************************************** Palette ********
// ****************************************************** Palette ********
// ****************************************************** Palette ********
// ****************************************************** Palette ********

void loadpal(paltype pal,int handle)
{
	read(handle,pal,768);
};

void savepal(paltype pal,int handle)
{
	write(handle,pal,768);
};




// ******************************************** Malroutinen *************
// ******************************************** Malroutinen *************
// ******************************************** Malroutinen *************
// ******************************************** Malroutinen *************
// ******************************************** Malroutinen *************
// ******************************************** Malroutinen *************



/*
void line_clip(spritetype *dest,int x1,int y1,int x2,int y2,char farbe)
{
	// Relativ zum Mittelpunkt machen
	x1+=dest->mx;
	x2+=dest->mx;
	y1+=dest->my;
	y2+=dest->my;

	char p1a=((x1<0)||(x1>=dest->sx)||(y1<0)||(y1>=dest->sy));
	char p2a=((x2<0)||(x2>=dest->sx)||(y2<0)||(y2>=dest->sy));
	if ((p1a)||(p2a))
	{
		float deltax=x2-x1;
		float deltay=y2-y1;
		float sx=(dest->sx)-1;
		float sy=(dest->sy)-1;

		int spx[2];
		int spy[2];
		char anzsp=0;

		if (p1a)
		{
			spx[1]=x2;
			spy[1]=y2;
		}else{
			spx[1]=x1;
			spy[1]=y1;
		}

		float s,t;
		if (deltax!=0)
		{
			// Schnitt mit linkem Rand ( deltax*s + x1 =x= 0      )
			//                         ( deltay*s + y1 =y= sy * t )
			s=-float(x1)/deltax;
			t=(deltay*s+float(y1))/sy;
			if ((t>=0.0)&&(t<=1.0)&&(s>=0.0)&&(s<=1.0))
			{
				// Schnittpunkt !!
				spx[anzsp]=0;
				spy[anzsp]=intsy*t;
				anzsp++;
			}

			// Schnitt mit rechten Rand ( deltax*s + x1 =x= sx     )
			//                          ( deltay*s + y1 =y= sy * t )
			s=(sx-float(x1))/deltax;
			t=(deltay*s+float(y1))/sy;
			if ((t>=0.0)&&(t<=1.0)&&(s>=0.0)&&(s<=1.0))
			{
				// Schnittpunkt !!
				spx[anzsp]=sx;
				spy[anzsp]=sy*t;
				anzsp++;
			}
		}

		if ((deltay!=0)&&(anzsp<2))
		{
			// Schnitt mit oberen Rand ( deltax*s + x1 =x= sx * t )
			//                         ( deltay*s + y1 =y= 0      )
			s=-float(y1)/deltay;
			t=(deltax*s+float(x1))/sx;
			if ((t>=0.0)&&(t<=1.0)&&(s>=0.0)&&(s<=1.0))
			{
				// Schnittpunkt !!
				spx[anzsp]=sx*t;
				spy[anzsp]=0;
				anzsp++;
			}

			if (anzsp<2)
			{
				// Schnitt mit unterem Rand ( deltax*s + x1 =x= sx * t )
				//                          ( deltay*s + y1 =y= sy     )
				s=(sy-float(y1))/deltay;
				t=(deltax*s+float(x1))/sx;
				if ((t>=0.0)&&(t<=1.0)&&(s>=0.0)&&(s<=1.0))
				{
					// Schnittpunkt !!
					spx[anzsp]=sx*t;
					spy[anzsp]=sy;
					anzsp++;
				}
			}
		}
		if (anzsp)
			lineintern(((char *)dest)+10,spx[0],spy[0],spx[1],spy[1],dest->sx,farbe);
	}else{
		lineintern(((char *)dest)+10,x1,y1,x2,y2,dest->sx,farbe);
	}
}

*/

// ************************************ Sprite Speicherobjekt !!!!!!!!!
// ************************************ Sprite Speicherobjekt !!!!!!!!!
// ************************************ Sprite Speicherobjekt !!!!!!!!!
// ************************************ Sprite Speicherobjekt !!!!!!!!!
/*
class sprite_classtype
{
public:
	// Pointer auf Sprite !!
	spritetype *spritetypeptr;
	// initpcxspritecheck
	sprite_classtype(int handle,uchar transcolor,paltype pal=(char*)NULL);
	// ladesprite !!!!!!!!!!!!!!
	sprite_classtype(int handle);
	// initemptyspritecheck
	sprite_classtype(uint sx,uint sy,int mx,int my,uchar transcolor);
	~sprite_classtype();
};

// initpcxspritecheck
sprite_classtype::sprite_classtype(int handle,uchar transcolor,paltype pal)
{
	int xanz,yanz;
	ulong spritesize,kompsize;
	spritetype *kompdata;
	_read(handle,workspace,128);

	if ((*workspace!=0xa)||(!workspace[2])||(workspace[3]!=8)||(workspace[65]!=1))
		fatalfehler("INITPCXSPRITECHECK: UNGÜLTIGE PCX DATEI");

	xanz=(*((int*)(workspace+8)))-(*((int*)(workspace+4)))+1;
	yanz=(*((int*)(workspace+10)))-(*((int*)(workspace+6)))+1;
	spritesize=ulong(xanz)*ulong(yanz)+10;
	spritetypeptr=(spritetype*)farmalloc(spritesize);

	kompsize=filelength(handle)-768-128-1;
	kompdata=(spritetype*)farmalloc(kompsize);
	_read(handle,kompdata,(int)kompsize);
	entkompasm(kompsize,(void*)((ulong)spritetypeptr+10),kompdata);
	farfree(kompdata);

	spritetypeptr->transcolor=transcolor;
	spritetypeptr->mx=0;
	spritetypeptr->my=0;
	spritetypeptr->sx=xanz;
	spritetypeptr->sy=yanz;

	if (pal)
	{
		lseek(handle,1,SEEK_CUR);
		loadpal(pal,handle);
		for(uint x=0;x<768;x++)pal[x]>>=2;
	}else{
		lseek(handle,769,SEEK_CUR);
	};
};

// ladesprite !!!!!!!!!!!!!!
sprite_classtype::sprite_classtype(int handle)
{
	_read(handle,workspace,10);
	uint anz=((spritetype*)workspace)->sx*((spritetype*)workspace)->sy;
	spritetypeptr=(spritetype*)farmalloc(10+anz);
	memcpy(spritetypeptr,workspace,10);
	_read(handle,((char*)spritetypeptr)+10,anz);
};

// initemptyspritecheck
sprite_classtype::sprite_classtype (uint sx,uint sy,int mx,int my,uchar transcolor)
{
	spritetypeptr=(spritetype*)farmalloc(sy*sx+10);

	spritetypeptr->transcolor=transcolor;
	spritetypeptr->mx=mx;
	spritetypeptr->my=my;
	spritetypeptr->sx=sx;
	spritetypeptr->sy=sy;
};

sprite_classtype::~sprite_classtype ()
{
  farfree((void *)spritetypeptr);
};

class sprite_class_algelemtype : public sprite_classtype, public algelemtype
{
	public:
	sprite_class_algelemtype(int handle,uchar transcolor,paltype pal=(char*)NULL)
		: sprite_classtype(handle,transcolor,pal){};
	sprite_class_algelemtype(int handle)
		: sprite_classtype(handle){};
	sprite_class_algelemtype(uint sx,uint sy,int mx,int my,uchar transcolor)
		:	sprite_classtype(sx,sy,mx,my,transcolor){};
};

class sprite_class_zeigerelemtype : public sprite_classtype, public zeigerelemtype<sprite_class_zeigerelemtype>
{
	public:
	sprite_class_zeigerelemtype(int handle,uchar transcolor,paltype pal=(char*)NULL)
		: sprite_classtype(handle,transcolor,pal){};
	sprite_class_zeigerelemtype(int handle)
		: sprite_classtype(handle){};
	sprite_class_zeigerelemtype(uint sx,uint sy,int mx,int my,uchar transcolor)
		:	sprite_classtype(sx,sy,mx,my,transcolor){};
};
machekettetype(sprite_class);


// ******************************************** Spritestapelliste ********
// ******************************************** Spritestapelliste ********
// ******************************************** Spritestapelliste ********
// ******************************************** Spritestapelliste ********
// ******************************************** Spritestapelliste ********
// ******************************************** Spritestapelliste ********

class sprite_class_stapeltype : public stapeltype<sprite_class_algelemtype>
{
	public:
	char *name;

	sprite_class_stapeltype (int handle,uint anz,char *dateiname);
	~sprite_class_stapeltype ();
};

sprite_class_stapeltype ::sprite_class_stapeltype (int handle,uint anz,char *dateiname)
{
	for (;anz;anz--)
	{
		zeiger_push(new sprite_class_algelemtype(handle));
	}
	name=(char*)farmalloc(1+strlen(dateiname));
	strcpy(name,dateiname);
};

sprite_class_stapeltype ::~sprite_class_stapeltype ()
{
	clear();
	farfree(name);
};

class sprite_class_stapel_zeigerelemtype : public sprite_class_stapeltype, public zeigerelemtype<sprite_class_stapel_zeigerelemtype>
{
	public:
	sprite_class_stapel_zeigerelemtype(int handle,uint anz,char *dateiname):sprite_class_stapeltype(handle,anz,dateiname){};
};


// ******************************************** Spritestapelkette *******
// ******************************************** Spritestapelkette *******
// ******************************************** Spritestapelkette *******
// ******************************************** Spritestapelkette *******
// ******************************************** Spritestapelkette *******

class sprite_class_stapel_kettetype : public kettetype<sprite_class_stapel_zeigerelemtype>
{
	public:
	sprite_class_stapel_zeigerelemtype *getspriteadress(char *n,uint anz);
};

sprite_class_stapel_zeigerelemtype *sprite_class_stapel_kettetype::getspriteadress(char *n,uint anzsprites)
{
	sprite_class_stapel_zeigerelemtype *akt=anfang->next;
	while (akt!=ende)
	{
		if (!strcmp(akt->name,n))
		{
			return(akt);
		};

		akt=akt->next;
	};
	int handle;
	openfile(&handle,n);
	sprite_class_stapel_zeigerelemtype *neu=new sprite_class_stapel_zeigerelemtype(handle,anzsprites,n);
	zeiger_addbefore(ende,neu);
	_dos_close(handle);
	return(neu);
};
*/
/*
void spritecollection::freespriteadress(char *n)
{
	zeigerelemtype <spriteclass> *akt=col.anfang->next;
	while (akt!=col.ende)
	{
		if (!strcmp(akt->name,n))goto fertig;

		akt=akt->next;
	};
	fatalfehler("Ein Sprite soll cleared werden, das nicht existiert");
	fertig:
	col.del(akt);
};

*/







/*

#pragma inline
#pragma warn -asm

void turnsprite(spritetype *dest, spritetype *source,float angle)
{
	float ya=sin(angle);   //sina !!!
	float xa=cos(angle);   //cosa !!!

	float rx=dest->mx;
	float ry=dest->my;
	float sy=source->my-rx*xa-ry*ya;
	float sx=source->mx+rx*ya-ry*xa;
	float wx=0,wy=0;
	int anz=dest->sx,anz2=source->sx;
	int *ofstab=(int*)farmalloc(anz<<1);

	for (int x=0;x<anz;x++)
	{
		ofstab[x]=int((int(wy+0.5)*anz2)+int(wx+0.5)+0.5);

		wx+=xa;
		wy+=ya;
	};

	for (int y=0;y<anz;y++)
	{
		int ofsa=int(sy+0.5)*anz2+int(sx+0.5);

		asm{
			cld

			push ds
			push si
			push di

			mov cx,anz

			les di,dest
			add di,10
			mov ax,y
			mul cx
			add di,ax

			lfs dx,source
			add dx,ofsa
			add dx,10
			movsx edx,dx

			lds si,ofstab
		};again:asm{
			lodsw
			cwde
			mov al,fs:[eax+edx]
			stosb
			loop again

			pop di
			pop si
			pop ds
		};

		sx-=ya;
		sy+=xa;
	};

	farfree(ofstab);
};
#pragma warn +asm*/
