/* NOTE: THIS IS A COMPILATION OF ALL THE RELATED SOURCE CODE. YOU CAN NOT
   COMPILE THIS! */

#include <dos.h>
#include <mem.h>
#include <math.h>
extern void clrscr(void);
void setmode(void)
{
	int i;
	static unsigned int CrtParms[]=
	 { 0xd06,0x3e07,0xc009,0xea10,0xac11,0xdf12,0x0014,0xe715,0x616,
		 0xe317 };
	_AX=0x13;
	geninterrupt(0x10);//}
	outport(0x3c4,0x604);
	outport(0x3c4,0x100);
	outportb(0x3c2,0xe3/*0xe7*/);
	outport(0x3c4,0x300);
	outportb(0x3d4,0x11);
	outportb(0x3d5,inportb(0x3d5)&0x7f);
	for (i=0;i<10;i++) outport(0x3d4,CrtParms[i]);
	clrscr();
}
#define C_EOB 0
#define C_EOS 0
#define CRUNCH(a,b) \ ((a)*16+(b))


#define C_LINE(X1,Y1,X2,Y2) \
	CRUNCH(X1,Y1),CRUNCH(((X1)+(X2))/2,((Y1)+(Y2))/2), \
	CRUNCH(((X1)+(X2))/2,((Y1)+(Y2))/2),CRUNCH(X2,Y2)
#define C_BEZIER(X1,Y1,X2,Y2,X3,Y3,X4,Y4) \
	CRUNCH(X1,Y1),CRUNCH(X2,Y2),CRUNCH(X3,Y3),CRUNCH(X4,Y4)

// All delays are in frames (1/70s)
char cmdtable[]={

//--------- 4 V1.0 ---------
 0x11,0x17,0x17,0x77,        // 4
 0x77,0x77,0x76,0x76,
 0x76,0x16,0x26,0x21,
 0x21,0x21,0x11,0x11,
 0x51,0x51,0x5b,0x5b,
 0x5b,0x5b,0x5b,0x5b,
 0x5b,0x5b,0x6b,0x6b,
 0x6b,0x6b,0x61,0x61,
 0x61,0x61,0x51,0x51,
 0x51,0x51,0x51,0x51,

 0x81,0x81,0x8b,0x8b,        // K
 0x8b,0x8b,0x9b,0x9b,
 0x9b,0x9b,0x91,0x91,
 0x91,0x91,0x81,0x81,

 0xb1,0x88,0x85,0xbb,
 0xbb,0xbb,0xcb,0xcb,
 0xcb,0x94,0x99,0xc1,
 0xc1,0xc1,0xb1,0xb1,

//------------------------
 0x01,0x11,0xb1,0xb6,0xb6,        // O
 0xb6,0xb6,0xa6,0xa6,
 0xa1,0xa2,0xa2,0x12,
 0x12,0x11,0x11,0x12,
 0x26,0x35,0x15,0xb5,
 0xb5,0xb5,0xb5,0xb5,
 0xb5,0xb6,0xb6,0xb6,
 0xb6,0x26,0x12,0x12,
 0x12,0x12,0x22,0x22,
 0x22,0x22,0x22,0x2c,

 0x17,0x18,0x18,0xb8,                            // R
 0xb8,0xb9,0xb9,0xb9,
 0xb9,0x19,0x2b,0x2b,
 0x2b,0x2b,0x1b,0x1b,

 0x1b,0x86,0x5b,0xbb,
 0xbb,0xbc,0xbc,0xbc,
 0xb8,0x5c,0x8c,0x2c,
 0x2c,0x1c,0x1b,0x10,

// ------------------------
 0x01,0x0b,0x0b,0x2b,                     // L
 0x2b,0x2b,0x2a,0x2a,
 0x2a,0x0a,0x1a,0x11,
 0x11,0x11,0x01,0x01,

 0x31,0x36,0x3b,0x3b,                       // E
 0x6b,0x6b,0x6a,0x6a,
 0x6a,0x3a,0x36,0x66,
 0x66,0x36,0x32,0x62,
 0x62,0x62,0x61,0x61,
 0x61,0x61,0x31,0x31,

 0xa1,0x51,0xba,0x7a,                             // S
 0x7a,0x7a,0x7b,0x7b,
 0x7b,0xcb,0x62,0xa2,
 0xa2,0xa2,0xa1,0xa1,

 0xd1,0x81,0xea,0xaa,                             // S
 0xaa,0xaa,0xab,0xab,
 0xab,0xfb,0x92,0xd2,
 0xd2,0xd2,0xd1,0xd1,

0x00

};
#define SIZECHANGE -2
#define ENDOFTABLE -1,-1

int lengthtable[]={
 60,60,
ENDOFTABLE
};

char delaytable[]={
 100,100,1
};

#include <dos.h>
#include <mem.h>
#include <stdio.h>
#include <stdlib.h>
#pragma inline
#define PROTECT
#define MATRIXSIZE 20

#define I asm
#define XPos 32
#define YPos 34
#define Xsize 128
#define Ysize 64
#define SCALE_FACTOR 16
//2
extern char Liike[];
extern int lasttodraw;
extern int *ScanRight;
extern int *ScanLeft;
extern int *ScanRCount;
extern int *ScanLCount;
extern long *sintaulu;
extern long *costaulu;

extern void pixel(int,int,int);
void CalcLandScape(void);
void setmode(void);
void piirralauta(void);
unsigned char *CurPalette;

typedef void (*funcptr)(void);

extern void ScanConvert(int x,int y,int x1,int y1,int *Scanner);
extern int *ScanRight;
extern int *ScanLeft;
void SetPage(unsigned offs)
{
I mov dx,03d4h
I mov bx,offs
I mov al,0ch
I mov ah,bh
I out dx,ax
I inc al
I mov ah,bl
I out dx,ax
}
volatile unsigned drawoffs=19200;

void rotate(int,int,int);
void LaskeSpeeds(void);

volatile int XN=0,YN=0;
volatile int KN=0;
volatile int XA,YA,KA;
int volatile TM;
volatile char *LiikePtr=Liike;

volatile int P_i=90,P_X=20,P_Y=20;
volatile int P_XCount=0,P_YCount=0,P_icount=0;
void VahennaTime(void)
{
		 if (lasttodraw>0) lasttodraw-=8;
		 if (TM>0) TM--; else
			{
			if (TM!=-1) {
				XA=LiikePtr[0];
				YA=LiikePtr[1];
				KA=LiikePtr[2];
				TM=LiikePtr[3];
				LiikePtr+=4;
			}
				else {lasttodraw+=16;return;}
			}

			P_icount+=(KN+=KA);
		if (P_icount<0) {P_i--;P_icount+=SCALE_FACTOR;} else
		if (P_icount>SCALE_FACTOR) {P_i++;P_icount-=SCALE_FACTOR;}
		if (P_i<0) P_i+=360;
		if (P_i>=360) P_i-=360;
		P_YCount+=(YN+=YA);
		if (P_YCount<0) {P_Y--;P_YCount+=SCALE_FACTOR;} else
		if (P_YCount>SCALE_FACTOR) {P_Y++;P_YCount-=SCALE_FACTOR;}
		P_XCount+=(XN+=XA);
		if (P_XCount<0) {P_X--;P_XCount+=SCALE_FACTOR;} else
				if (P_XCount>SCALE_FACTOR) {P_X++;P_XCount-=SCALE_FACTOR;}
}

void CalcSinTable(void);



extern char *landscape;
extern long *XCoord;
extern long *YCoord;
extern int *XIndex;
extern int *YIndex;
extern int *XIndex1;
extern int *YIndex1;
extern long *matrixZ;
extern void far TimerHandler(void);
void SetIntVec(char,unsigned,unsigned);

void clrscr(void)
{
	 I push es
	outport(0x3c4,0x0f02);
	_ES=0xa000;
	_EDI=drawoffs;
	_ECX=4800;
	_EAX=0;
	I rep stosd
	I pop es
}
void waitscreen(void);

void main_1()
{
	char  l_andscape[22500];
	long AXCoord[MATRIXSIZE*MATRIXSIZE];
	long AYCoord[MATRIXSIZE*MATRIXSIZE];
	int AXIndex[(MATRIXSIZE+1)*(MATRIXSIZE+1)];
	int AYIndex[(MATRIXSIZE+1)*(MATRIXSIZE+1)];
	int AXIndex1[(MATRIXSIZE+1)*(MATRIXSIZE+1)];
	int AYIndex1[(MATRIXSIZE+1)*(MATRIXSIZE+1)];
	long AMatrixZ[MATRIXSIZE*MATRIXSIZE];
	long A_sintaulu[360],A_costaulu[360];
	int End_effect(void);
	int j,item;
	XCoord=AXCoord;
	YCoord=AYCoord;
	XIndex=AXIndex;
	YIndex=AYIndex;
	XIndex1=AXIndex1;
	YIndex1=AYIndex1;
	_DI=(int)(matrixZ=AMatrixZ);
	_ES=_DS;
	_CX=MATRIXSIZE*MATRIXSIZE/4;
	asm rep stosd
	drawoffs=0;
	clrscr();

	landscape=l_andscape;
	sintaulu=A_sintaulu;costaulu=A_costaulu;

		_AX=0;
		_BX=980;
		_CX=_BX;
		_DI=(int)ScanRight;
		I rep stosw
		_CX=_BX;
		_DI=(int)ScanLeft;
		I rep stosw
		_CX=_BX;
		_DI=(int)ScanRCount;
		I rep stosw
		_CX=_BX;
		_DI=(int)ScanLCount;
		I rep stosw;
	 drawoffs=19200;
	 clrscr();
	 CalcSinTable();
	 CalcLandScape();
	 XA=LiikePtr[0];
	 YA=LiikePtr[1];
	 KA=LiikePtr[2];
	 TM=LiikePtr[3];
	 LiikePtr+=4;

	SetIntVec(0x8,FP_OFF(TimerHandler),_CS);
	#ifdef PROTECT
	I mov al,0feh
	I out 021h,al
	#endif
	for (;(TM!=-1 || lasttodraw<MATRIXSIZE*MATRIXSIZE);) {
		rotate(P_i,P_X,P_Y);

		piirralauta();

		waitscreen();

		drawoffs^=19200;
		outport(0x3c4,0x0f02);

		I mov ax,0a000h
		I mov es,ax
		I mov di,word ptr drawoffs
		I add di,3300
		I mov cx,4062
		I xor eax,eax
		I rep stosd
	}
}
char Liike[]={
	0  ,0  ,0  ,50,
	0  ,0  ,-3 ,20,
	0  ,0  ,0  ,3 ,
	0  ,0  ,3  ,20,
	0  ,1  ,0  ,20,
	0  ,-1 ,-1 ,20,
	0  ,0  ,0  ,20,
	1 ,1  ,0   ,20,
	-1  ,-1 ,0 ,20,
	1  ,0  ,0  ,20,
	0  ,0  ,1  ,50,
	-1 ,0  ,-1 ,20,
	0  ,0  ,-1 ,30,
	0  ,0  ,1  ,20,
	0  ,-1 ,0  ,25,
	0  ,1  ,1  ,25,
	1  ,0  ,-1 ,30,
	0  ,0  ,0  ,50,
	-1 ,1  ,-1 ,15,
	0  ,0  ,0  ,30,
	-1 ,-1 ,1  ,15,
	0  ,0  ,1  ,5 ,
	0  ,0  ,0  ,50,
	0  ,0  ,0  ,-1

};
#include <dos.h>
#pragma asm
#define PROTECT
#define I asm
extern void bezier(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int color);
void scanconvert2(int,int,int,int,int);
void SetPage(unsigned);

extern unsigned drawoffs;

extern char cmdtable[];
extern int lengthtable[];
extern char delaytable[];

int *wcmdtable;
int *wcmdtable2;
int *xspeed;
int *yspeed;
int color=60;
int oldframes=0;
int framecount=0;
int * cnvrt(register int *a,register int *b,int frames)
{
	int ispeed;
	if (frames!=oldframes) {framecount=0; oldframes=frames; }
												 else framecount++;
	if (frames==1) {
		a[0]=b[0];a[1]=b[1];} else {
	frames--;
	a[0]+=(
				 xspeed[framecount]+=
						( ( (((b[0])-(a[0])) /frames)-xspeed[framecount]) )>>2   );
	a[1]+=(yspeed[framecount]+=
		((((b[1])-(a[1]))/(frames)-yspeed[framecount])) >>2) ;
	}
	return a+2;
}

int *cnvrtbezier(int *a,int *b,const int frames,int nro)
{
	int i,*k;
	for (i=0;i<=nro;i+=2)
		k=cnvrt(a+i,b+i,frames);
	return k;
}

typedef int * (*CNVRTFUNC)(int *,int *,const int);
int *convert(register int *a,int *b,const int frames)
{
	int nro=6;
	do {
				register int *p=cnvrtbezier(a,b,frames,nro);
			b+=p-a; a=p;
			nro=2;
	 } while (*a);
		return a+1;
}

int beziernro=1;
extern int *ScanLeft;
extern int *ScanRight;
char *ScanMark;
void ScanConvert(int,int,int,int,int *);
void Fillpatch(int,int,long);

void scanconvert2(int x1,register int y1,int x2,register int y2,int color)
{
	int markcode,i,sx;
	if (y1==y2) return;
	if (y2>=240) y2=239;
	if (y1>=240) y1=239;
	if (y1>y2) {
		I mov ax,y1
		I xchg ax,y2
		I mov y1,ax
		I mov ax,x1
		I xchg ax,x2
		I mov x1,ax
		}
	x1+=32;x2+=32;
	if ((ScanMark[y1+1]==0 && ScanMark[y2-1]==0) || (ScanMark[y1+1]==beziernro || ScanMark[y2-1]==beziernro)) {
		markcode=beziernro;
		ScanConvert(x1,y1,x2,y2,ScanLeft);
	} else
	{
		int A,temp;
		markcode=0;
		ScanConvert(x1,y1,x2 ,y2,ScanRight);
		for (A=y1;A<y2;A++) {
			I movzx eax,word ptr A
			I movzx ebx,word ptr ScanLeft
			I movzx ecx,word ptr ScanRight
			I mov dx,[eax*2+ebx]
			I cmp dx,[eax*2+ecx]
			I jle no_swap
			I xchg dx,[eax*2+ecx]
			I mov [eax*2+ebx],dx
no_swap:

		}
		_AL=color;
		_AH=_AL;
		I push ax
		I push ax
		I pop ecx
		Fillpatch(y1,y2,_ECX);
	}
	for (i=y1;i<y2;i++) ScanMark[i]=markcode;
}


#define SET_RES(a)
#define ENABLE_SET(a)
#define SET_RES1(a)
#define ENABLE_SET1(a)


int * draw(register const int *p)
{
	beziernro=1;
 _ES=_CS;
 _DI=(int)ScanMark;
 _CX=120;
 _EAX=0;
	I rep stosd
	do {
		bezier(p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],color);
		p+=8;
		beziernro++;
	} while (*p);
	return (int *)++p;
}
void waitscreen(void)
{
	while((inportb(0x3da)&8));
	SetPage(drawoffs);
	while(0==(inportb(0x3da)&8));
}
void clrscr(void);

void partdo(int frame)
{
	convert(wcmdtable,draw(wcmdtable),frame);
	waitscreen();
	drawoffs^=19200;
	clrscr();
}


void setmode(void);
extern unsigned char *CurPalette;
extern void DoSetPalette(char *pal);
int main_2(void)
{
 char *p;
 char _ScanMark[482];
 int _wcmdtable[2000];
 int frame,temp,i;
 int _xspeed[2000],_yspeed[2000];
 int lengthindex=0;
 ScanMark=_ScanMark;
 _ES=_DS;
 _SI=(int)cmdtable;
 _DI=(int)_wcmdtable;
 _CX=1000;
 _AH=0;
loopppi:
I lodsb
I mov dl,al
I and ax,0f0h
I shl ax,4
I stosw
I mov al,dl
I and ax,0fh
I shl ax,8
I stosw
I loop loopppi
 xspeed=_xspeed;


 yspeed=_yspeed;
 _DI=FP_OFF(ScanMark);
 _CX=482;
 asm rep stosb

 wcmdtable=_wcmdtable;
 setmode();
 SetPage(19200);
	 for (temp=0,i=0;temp<63;temp++,i+=3)
	 {
				CurPalette[i+1]=CurPalette[i]=temp/2;
				CurPalette[i+2]=temp;

	 }

	 I push es
		_ES=_DS;
		_DX=FP_OFF(CurPalette);
		_CX=256;
		_BX=0;
		_AX=0x1012;
		geninterrupt(0x10);
 I pop es

 draw(wcmdtable);
 for (frame=0;frame<100;frame++) waitscreen();
 do {
 _ES=_DS;
 _CX=2000;
 _BX=_CX;
 _DI=(int)xspeed;
 _AX=0;
I rep stosw
 _DI=(int)yspeed;
 _CX=_BX;
 _AX=0;
I rep stosw

	 for (frame=lengthtable[lengthindex];frame>0;frame--) {
		partdo(frame);
		partdo(--frame);
	}
		wcmdtable=draw(wcmdtable);

		_CX=(unsigned char)delaytable[lengthindex];
l1:
		I push cx
		waitscreen();
		I pop cx
		I loop l1
 } while (lengthtable[++lengthindex]!=-1);
 return 0;
}

extern int *ScanRCount;
extern int *ScanLCount;
extern void main_1(void);

typedef void far *HANDLER;
HANDLER  OldKbHandler,OldTimerHandler;

void VahennaTime(void);

void far TimerHandler(void)
{
I pusha
I push cs
I pop ds
I call near ptr VahennaTime
I mov al,20h
I out 20h,al
I popa
I iret
}

void SetIntVec(char nro,int hoff,int hseg)
{
	asm push ds
	_DS=hseg;
	_DX=hoff;
	_AH=0x25;
	_AL=nro;
	geninterrupt(0x21);
	asm pop ds
}

void main()
{
	int Iseg,Iofs;
	int  A_ScanRight[980];
	int  A_ScanLeft[980];
	int  A_ScanRCount[980];
	int  A_ScanLCount[980];
	char  c_urpalette[768];
	#ifdef PROTECT
	I mov al,0ffh
	I out 021h,al
	#endif

	ScanRight=A_ScanRight;
	ScanLeft=A_ScanLeft;
	ScanRCount=A_ScanRCount;
	ScanLCount=A_ScanLCount;
	CurPalette=c_urpalette;

	asm push es
	_AX=0x3508;
	geninterrupt(0x21);
	Iseg=_ES;
	Iofs=_BX;

	asm pop es
	main_2();
	main_1();
	I cli
	SetIntVec(0x8,Iofs,Iseg);
#ifdef PROTECT

	I mov al,0b0h
	I out 021h,al
#endif
	_AX=3;
	geninterrupt(0x10);
}
#include <dos.h>
#include <stdlib.h>

#pragma inline
#define I asm

#define MATRIXSIZE 20
#define MATRIXLEN 8
#define MATCONST2 2560
#define COLORDIV 930
int lasttodraw=MATRIXSIZE*MATRIXSIZE - 1;

int *ScanRight;
int *ScanLeft;
int *ScanRCount;
int *ScanLCount;
extern unsigned drawoffs;
long *sintaulu;
long *costaulu;

#define LANDXSIZE 150
#define LANDYSIZE 150

char *landscape;


void CalcLandScape(void)
{
	register int i,j;
	for (i=0;i<LANDYSIZE;i++)
		for (j=0;j<LANDXSIZE;j++)
		{
			int i2=i-80,j2=j-50;

			long korkeus=((sintaulu[(((i2*i2-j2*i2)/(5))%350)+5]+32000L)>>9)+
														((sintaulu[(((j-20)*30)%350)+5]+33000L)>>9);
			if (korkeus<0) korkeus=0;
			landscape[i*LANDXSIZE+j]=(char)korkeus;
		}
}

long *matrixZ;


void CalcSinTable(void)
{
	long v,x,vc=0,xc=0,AA=193948423;
	register int i;
	x=32768L;v=0;
	for (i=0;i<=360;i++) {
		costaulu[i]=x;
		_EAX=x << 15;
		I cdq
		I shl eax,1
		I rcl edx,1
		I idiv dword ptr AA

		I sub vc,edx
		I sbb v,eax
		_EAX=vc;
		_EDX=v;
		I add xc,eax
		I adc x,edx
	}
	for (i=0;i<360;i++) {
		if (i<=90) sintaulu[i]=costaulu[90-i]; else
							 sintaulu[i]=costaulu[360+90-i];
	}
}

void ScanConvert(int x1,int y1,int x2,int y2,int *Scanner)
{
	int x,y;
	int k,kj;
	int DxA,Dy;
	int count;
	int Sx;
		Sx=((DxA=x2-x1)<0)?-1:1;
	if ((Dy=y2-y1)<0)
	{
		int temp=x1;x1=x2;x2=temp;
		temp=y1;y1=y2;y2=temp;
		I neg word ptr Dy
		I neg word ptr DxA
		I neg word ptr Sx
	}
		I cmp word ptr Dy,0
		I jnl ei_pienempi
		I neg word ptr Dy
ei_pienempi:
		I jnz ei_nolla
		Scanner[y1]=x1;
		return;
ei_nolla:
	I mov ax,DxA
	I cwd
	I idiv word ptr Dy
	I mov word ptr k,ax
	I mov word ptr kj,dx
	I cmp dx,0
	I jnl ei_pienempi1
	I neg word ptr kj
ei_pienempi1:
	Sx+=k;
	count=0;
	_DI=FP_OFF(Scanner);
	_BX=y1;
	_DX=y2;
	I cmp dx,480
	I jng ei__
	I mov dx,480
ei__:
	I shl bx,1
	I shl dx,1
	I add bx,di
	I add dx,di
	_DI=count;
	_CX=kj;
	_AX=x1;
looppi:
	I mov [bx],ax
ei_first:
	I add di,cx
	I jng ei_toinen1
	I add ax,Sx
	I mov si,Dy
	I sub di,si
ei_toinen:
	I add bx,2
	I cmp bx,dx
	I jle looppi
	I jmp kylla_toinen
ei_toinen1:
	I add ax,k
	I add bx,2
	I cmp bx,dx
	I jle looppi
kylla_toinen:;
}

void Fillpatch(int y1,int y2,long color)
{
	int x1,x2,y,Dx,sDx,eDx,i,oy;
	char *p;
	static unsigned char LeftMask[]={0xf,0xe,0xc,0x8};
	static unsigned char RightMask[]={1,3,7,0xf};
	oy=y1;
	while (ScanRight[oy]>=320) ScanRight[oy++]=319;
	oy=y2;
	while (ScanRight[oy]>=320) ScanRight[oy--]=319;
	oy=y1;
	while (ScanLeft[oy]<0) ScanLeft[oy++]=0;
	oy=y2;
	while (ScanLeft[oy]<0) ScanLeft[oy--]=0;
	 p=(char *)(y1*80+drawoffs);
	outportb(0x3c4,2);
	_ES=0xa000;
	for (y=y1;y<=y2;y++,p+=80) {
		I .386
		_DI=FP_OFF(ScanLeft);
		I mov bx,word ptr y
		I shl bx,1
		I mov si,[bx+di]
		_DI=FP_OFF(ScanRight);
		I mov cx,[bx+di]
		I cmp si,cx
		I jne ei_pois
		continue;
ei_pois:
		I jbe ei_vaihtoa
		I xchg si,cx
		I mov [bx+di],cx
		_DI=FP_OFF(ScanLeft);
		I mov [bx+di],si
ei_vaihtoa:
		_DI=FP_OFF(p);

		I mov dx,si
		I and si,3
		I mov al,[si+offset LeftMask]
		I shr cx,2
		I shr dx,2
		I add di,dx
		I sub cx,dx
		I mov dx,03c5h;
		I jle only_one_byte
		I out dx,al
		I mov eax,color
		I stosb
		I mov al,15
		I sub cx,2
		I jz three_bytes
		I jnl not_only_two_bytes
		I jmp only_one_byte
three_bytes:
		I out dx,al
		I mov eax,color
		I stosb
		I mov al,15
		I       jmp only_one_byte
not_only_two_bytes:
		I out dx,al
			I .386
			I inc cx
			I mov eax,color
			I shr cx,1
			I jnc ei_byte
			I stosb
ei_byte:;
			I shr cx,1
			I jnc ei_word
			I stosw
ei_word:;
			I rep stosd
			I mov al,15

only_one_byte:
	 I push di
	 _DI=FP_OFF(ScanRight);
	 I mov bx,[bx+di]
	 I pop di
	 I and bx,3
	 I and al,[bx+offset RightMask]
	 I out dx,al
	 I mov eax,color
	 I stosb
	}
}

void patch(int *x,int *y,unsigned long color)
{
	int i,MaxIndex,Temp,AA;
	register int MinIndexR,MinIndexL;
	int MinPointY,MaxPointY,TopIsFlat,LeftEdgeDir;
	int CurIndex,PrevIndex;
	int *ScanK;

	MaxPointY=MinPointY=y[MinIndexL=MaxIndex=0];
	for (i=1;i<4;i++) {
		if (y[i]<MinPointY) MinPointY=y[MinIndexL=i]; else
		if (y[i]>MaxPointY) MaxPointY=y[MaxIndex=i];
	}
	if (MinPointY==MaxPointY) return;
	MinIndexR=MinIndexL;
	while (y[MinIndexR]==MinPointY) {MinIndexR++;MinIndexR&=3;}
	MinIndexR--;MinIndexR&=3;
	while (y[MinIndexL]==MinPointY) {MinIndexL--;MinIndexL&=3;}
	MinIndexL++;MinIndexL&=3;
	LeftEdgeDir=-1;
	if (0!=(TopIsFlat=(x[MinIndexL]!=x[MinIndexR]) & 1)) {//?1:0)==1) {
		if (x[MinIndexL]>x[MinIndexR]) {
			LeftEdgeDir=1;
			Temp=MinIndexL;
			MinIndexL=MinIndexR;
			MinIndexR=Temp;
		}
	}
	if (MaxPointY-MinPointY-1+TopIsFlat<=0) return;
	PrevIndex=CurIndex=MinIndexL;
	ScanK=ScanLeft;
	for (AA=0;AA<2;AA++) {
		do {
			CurIndex+=LeftEdgeDir;CurIndex&=3;
			ScanConvert(x[PrevIndex],y[PrevIndex],x[CurIndex],y[CurIndex],ScanK);
			PrevIndex=CurIndex;
		} while (CurIndex!=MaxIndex);
		PrevIndex=CurIndex=MinIndexR;
		I neg word ptr LeftEdgeDir
		ScanK=ScanRight;
	}

	if (MaxPointY>=240) MaxPointY=239;
	for (i=MinPointY;i<=MaxPointY;i++)
	{
		if (ScanRight[i]<0) ScanRight[i]=0;
		if (ScanRight[i]>=320) ScanRight[i]=319;
		if (ScanLeft[i]<0) ScanLeft[i]=0;
		if (ScanLeft[i]>=320) ScanLeft[i]=319;
	}
	Fillpatch(MinPointY,MaxPointY,color);
}

long *XCoord;
long *YCoord;
int *XIndex;
int *YIndex;
int *XIndex1;
int *YIndex1;

void rotate(int kulma,int xp,int yp)
{
	int i,j;
	long sinalfa,cosalfa,Zsinalfa,Zcosalfa,Xcosalfa,Xsinalfa,Dsin,Dcos,DsinTemp,DcosTemp;
	int offs1;
	I movzx ebx,word ptr kulma
	I movzx eax,word ptr sintaulu
	I mov esi,[eax+ebx*4]
	I movzx ecx,word ptr costaulu
	I mov edi,[ebx*4+ecx]
	I imul eax,esi,-MATCONST2
	I mov Zsinalfa,eax
	I mov Xsinalfa,eax
	I mov DsinTemp,eax
	I imul eax,edi,-MATCONST2
	I mov Zcosalfa,eax
	I mov Xcosalfa,eax
	I mov DcosTemp,eax
	I imul eax,esi,MATRIXLEN*2*16
	I mov Dsin,eax
	I imul eax,edi,MATRIXLEN*2*16
	I mov Dcos,eax

	for (i=0;i<MATRIXSIZE;i++)
	{
		for (j=0;j<MATRIXSIZE;j++)
		{

			int Z;

			_AL=(landscape[(i+yp)*LANDXSIZE+j+xp]&255);
			_AH=0;
	I mov ecx,dword ptr Xcosalfa
	I add ecx,dword ptr Zsinalfa
	I push ecx
	I mov ecx,dword ptr Zcosalfa
	I sub ecx,dword ptr Xsinalfa
	I cwde
			I shl eax,17
			I mov esi,eax
			I mov edi,ecx
			I sar ecx,1
			I add esi,ecx
			I neg esi
			I sar eax,1
			I sub edi,eax
			I mov ecx,edi
			I sar edi,12
			matrixZ[offs1=i*MATRIXSIZE+j]=_EDI;

			I pop eax
			I sar ecx,1
			I sar esi,1
			I sar eax,1

			I add ecx,0x4020000
			I jnl ei_neg
			XCoord[offs1]=-5000;
			YCoord[offs1]=-5000;
			I jmp save_values

ei_neg:
			I mov edx,100*2
			I imul edx
			I idiv ecx
			I pop ecx*/

			I push ecx
			I movzx ebx,word ptr offs1
			I movzx ecx,word ptr XCoord
			I mov dword ptr [ecx+ebx*4],eax
			I pop ecx


			I mov eax,esi
			I mov edx,100*2
			I imul edx
			I idiv ecx

			I movzx ecx,word ptr YCoord
			I mov dword ptr [ecx+ebx*4],eax

save_values:
			I mov eax,Dcos
			I add Xcosalfa,eax
			I mov eax,Dsin
			I add Xsinalfa,eax
		}
		I mov eax,Dcos
		I add Zcosalfa,eax
		I mov eax,Dsin
		I add Zsinalfa,eax

		I mov eax,DcosTemp
		I mov Xcosalfa,eax

		I mov eax,DsinTemp
		I mov Xsinalfa,eax

	}

}

void SortIndexes(int mini,int maxi)
{
	int k,data1,data2;
	register int i,j;
	int d;
	if (maxi>mini) {
		d=(mini+maxi)>>1;
		SortIndexes(mini,d);
		SortIndexes(d+1,maxi);
		I mov ax,ds
		I mov es,ax
		I movzx eax,word ptr mini
		I movzx esi,word ptr XIndex
		I movzx edi,word ptr XIndex1
		I lea esi,[esi+2*eax]
		I lea edi,[edi+2*eax]
		I movzx ecx,word ptr maxi
		I sub ecx,eax
		I inc ecx
		I shr ecx,1
		I jnc ei_wordi
		I movsw
ei_wordi:
		I rep movsd

		I movzx esi,word ptr YIndex
		I movzx edi,word ptr YIndex1
		I movzx eax,word ptr mini
	 I lea esi,[esi+2*eax]
	 I lea edi,[edi+2*eax]
		I movzx ecx,word ptr maxi
		I sub ecx,eax
		I inc ecx
		I shr ecx,1
		I jnc ei_wordi1
		I movsw
ei_wordi1:
		I rep movsd


	 for (i=k=mini,j=d+1;k<=maxi;k++)
			if (i>d)
				{XIndex[k]=XIndex1[j];YIndex[k]=YIndex1[j++];} else
			if (j>maxi)
				{XIndex[k]=XIndex1[i];YIndex[k]=YIndex1[i++];} else

			if (matrixZ[XIndex1[i]*MATRIXSIZE+YIndex1[i]]<matrixZ[XIndex1[j]*MATRIXSIZE+YIndex1[j]])
				{XIndex[k]=XIndex1[i];YIndex[k]=YIndex1[i++];} else
				{XIndex[k]=XIndex1[j];YIndex[k]=YIndex1[j++];}

	}
}


void DoSortIndex(void)
{
	static int Done=0;
	register int i,j;
	if (!Done) { Done=1;
	 I movzx esi,XIndex
	 I movzx edi,YIndex
	 I xor eax,eax
	 I mov dx,MATRIXSIZE-1
l2:
	 I mov cx,MATRIXSIZE-1
l1:
	 I mov word ptr [esi+eax*2],dx
	 I mov word ptr [edi+eax*2],cx
	 I inc ax
	 I loop l1
	 I dec dx
	 I jnl l2
	}
	SortIndexes(0,MATRIXSIZE*MATRIXSIZE-1);
}

void piirralauta(void)
{
	int tabX[4],tabY[4];
	int i,j;
	int k;
	int color;

	DoSortIndex();
	for (k=MATRIXSIZE*MATRIXSIZE;k>=lasttodraw;k--)
		{
			int AA;
			register long *XAPtr,*YAPtr;
			i=XIndex[k];
			j=YIndex[k];
			AA=i*MATRIXSIZE+j;
			if ((unsigned)i>=MATRIXSIZE-1 || (unsigned)j>=MATRIXSIZE-1) continue;

			XAPtr=XCoord+AA;
			tabX[0]=XAPtr[0]+160;
			tabX[1]=XAPtr[MATRIXSIZE]+160;
			tabX[2]=XAPtr[MATRIXSIZE+1]+160;
			tabX[3]=XAPtr[1]+160;

			YAPtr=YCoord+AA;
			tabY[0]=YAPtr[0]+120;
			tabY[1]=YAPtr[MATRIXSIZE]+120;
			tabY[2]=YAPtr[MATRIXSIZE+1]+120;
			tabY[3]=YAPtr[1]+120;
			color=30-(matrixZ[AA]/COLORDIV);

			if ((tabX[0] & tabX[1] & tabX[2] & tabX[3])<0) continue;
			if (tabX[0]>=320 && tabX[1]>=320 && tabX[2]>=320 && tabX[3]>=320) continue;
			if (tabY[0]>=240 && tabY[1]>=240 && tabY[2]>=240 && tabY[3]>=240) continue;
			if ((tabY[0]|tabY[1]|tabY[2]|tabY[3])<0) {continue;}

				_ECX=color;
				_CH=_CL;
				I push Cx
				I push Cx
				I pop eCx
				patch((int*)tabX,(int*)tabY,_ECX);
		}
}


.model tiny,Pascal
.386
dosseg
locals
bezier_only = 1

screen_seg segment para public use16
screen_seg ends

.code
extrn scanconvert2:proc

public bezier

oldsp dw 0
oldss dw 0
allocaddr dw 0
currentx dw 0
currenty dw 0
depth dw 0
bezier_t proc x1:WORD,y1:WORD,x2:WORD,y2:WORD,x3:WORD,y3:WORD,x4:WORD,y4:WORD,color:WORD
	local r1x:WORD,r1y:WORD,r2x:WORD,r2y:WORD,r3x:WORD,r3y:WORD,q1x:WORD,q1y:WORD,q2x:WORD,q2y:WORD,s1x:WORD,s1y:WORD
	mov ax,x2
	mov bx,ax
	add ax,x1
	shr ax,1
	mov r1x,ax
	mov cx,x3
	add bx,cx
	shr bx,1
	add cx,x4
	shr cx,1
	mov r3x,cx
	add cx,bx
	add ax,bx
	shr ax,1
	shr cx,1
	mov q1x,ax
	mov q2x,cx
	add ax,cx
	shr ax,1
	mov s1x,ax
	mov ax,y2
	mov bx,ax
	add ax,y1
	shr ax,1
	mov r1y,ax
	mov cx,y3
	add bx,cx
	shr bx,1
	add cx,y4
	shr cx,1
	mov r3y,cx
	add cx,bx
	add ax,bx
	shr ax,1
	shr cx,1
	mov q1y,ax
	mov q2y,cx
	add ax,cx
	shr ax,1
	mov s1y,ax
	dec depth
	cmp depth,0
	jnz ei_lopetus
	shr s1x,4
	shr s1y,4
	call scanconvert2,currentx,currenty,s1x,s1y,color
	mov ax,s1x
	mov currentx,ax
	mov ax,s1y
	mov currenty,ax
	inc depth
	ret
ei_lopetus:
	call bezier_t,x1,y1,r1x,r1y,q1x,q1y,s1x,s1y,color
	call bezier_t,s1x,s1y,q2x,q2y,r3x,r3y,x4,y4,color
	inc depth
	ret
endp
bezier proc x1:WORD,y1:WORD,x2:WORD,y2:WORD,x3:WORD,y3:WORD,x4:WORD,y4:WORD,color:WORD
	mov cl,4
	mov depth,8
	mov ax,x1
	mov currentx,ax
	mov ax,y1
	mov currenty,ax
	shr currentx,cl
	shr currenty,cl
	call bezier_t,x1,y1,x2,y2,x3,y3,x4,y4,color
	shr x4,4
	shr y4,4
	call scanconvert2,currentx,currenty,x4,y4,color
	ret

endp

do_it:

endp

end

	NAME    c0
	PAGE    60,132
	LOCALS
;[]------------------------------------------------------------[]
;|      C0.ASM -- Start Up Code                                 |
;|                                                              |
;|      Turbo C++ Run Time Library                              |
;|                                                              |
;|      Copyright (c) 1987, 1991 by Borland International Inc.  |
;|      All Rights Reserved.                                    |
;[]------------------------------------------------------------[]

								__C0__ = 1
				__TINY__ = 1
INCLUDE         C:\BORLANDC\LIB\STARTUP\RULES.ASI
dosseg
;       Segment and Group declarations

_TEXT           SEGMENT BYTE PUBLIC 'CODE'
		ENDS
_FARDATA        SEGMENT PARA PUBLIC 'FAR_DATA'
		ENDS
_FARBSS         SEGMENT PARA PUBLIC 'FAR_BSS'
		ENDS
IFNDEF __TINY__
_OVERLAY_       SEGMENT PARA PUBLIC 'OVRINFO'
		ENDS
_1STUB_         SEGMENT PARA PUBLIC 'STUBSEG'
		ENDS
ENDIF
_DATA           SEGMENT PARA PUBLIC 'DATA'
		ENDS
_INIT_          SEGMENT WORD PUBLIC 'INITDATA'
InitStart       label byte
		ENDS
_INITEND_       SEGMENT BYTE PUBLIC 'INITDATA'
InitEnd         label byte
		ENDS
_EXIT_          SEGMENT WORD PUBLIC 'EXITDATA'
ExitStart       label byte
		ENDS
_EXITEND_       SEGMENT BYTE PUBLIC 'EXITDATA'
ExitEnd         label byte
		ENDS
_CVTSEG         SEGMENT WORD PUBLIC 'DATA'
		ENDS
_SCNSEG         SEGMENT WORD PUBLIC 'DATA'
		ENDS
IFNDEF __HUGE__
  _BSS          SEGMENT WORD PUBLIC 'BSS'
		ENDS
  _BSSEND       SEGMENT BYTE PUBLIC 'BSSEND'
		ENDS
ENDIF
IFNDEF __TINY__
  _STACK        SEGMENT STACK 'STACK'
		ENDS
ENDIF

	ASSUME  CS:_TEXT, DS:DGROUP

;       External References

extrn           MAIN:DIST;_main:DIST
extrn           _exit:DIST
extrn           __exitbuf:DIST
extrn           __exitfopen:DIST
extrn           __exitopen:DIST
extrn           __setupio:near                  ;required!
extrn           __stklen:word
IF LDATA EQ false
extrn           __heaplen:word
ENDIF

	SUBTTL  Start Up Code
	PAGE
;/*                                                     */
;/*-----------------------------------------------------*/
;/*                                                     */
;/*     Start Up Code                                   */
;/*     -------------                                   */
;/*                                                     */
;/*-----------------------------------------------------*/
;/*                                                     */
PSPHigh         equ     00002h
PSPEnv          equ     0002ch
PSPCmd          equ     00080h

		public  __AHINCR
__AHINCR        equ     1000h
		public  __AHSHIFT
__AHSHIFT       equ     12

IFDEF   __NOFLOAT__
MINSTACK        equ     128     ; minimal stack size in words
ELSE
MINSTACK        equ     256     ; minimal stack size in words
ENDIF
;
;       At the start, DS and ES both point to the segment prefix.
;       SS points to the stack segment except in TINY model where
;       SS is equal to CS
;
_TEXT           SEGMENT
		ORG     100h
STARTX          PROC    NEAR
		mov     dx, cs;DGROUP      ; DX = GROUP Segment address
		mov     ds, dx
;;                mov oldss,ss
;;                mov oldsp,sp
		mov bx,0fffeh;;offset DGROUP:stack__end
		cli                     ; req'd for pre-1983 88/86s
		;;mov dx,seg _STACK
		mov     ss, dx          ; Set the program stack
		mov     sp, bx;;offset DGROUP:stack__end-2
		sti
		call    MAIN;_main

;;                mov dx,oldss
;;                mov bx,oldsp
;;                cli
;;                mov ss,dx
;;                mov sp,bx
;;                sti
ExitToDOS       label   near
								mov     ax,4C00h
								int     21h                     ; Exit to DOS
STARTX          ENDP
;;oldss dw 0
;;oldsp dw 0


	SUBTTL  Vector save/restore & default Zero divide routines
	PAGE



; The DGROUP@ variable is used to reload DS with DGROUP

;PubSym@         DGROUP@, <dw    ?>, __PASCAL__

; __MMODEL is used to determine the memory model or the default
; pointer types at run time.

;                public __MMODEL
;__MMODEL        dw      MMODEL

_TEXT           ENDS

		SUBTTL  Start Up Data Area
		PAGE

_DATA           SEGMENT

;       Magic symbol used by the debug info to locate the data segment
		public DATASEG@
DATASEG@        label   byte


_DATA           ENDS


_CVTSEG         SEGMENT
PubSym@         _RealCvtVector, <label  word>,  __CDECL__
		ENDS

_SCNSEG         SEGMENT
PubSym@         _ScanTodVector,  <label word>,  __CDECL__
		ENDS

_BSS            SEGMENT
bdata@          label   byte
		ENDS

_BSSEND         SEGMENT
edata@          label   byte
		ENDS
;public stack__end
;_STACK          SEGMENT
;stack___           db      128 dup(?) ;;49152 dup(?)               ;minimum stack size
;stack__end         db ?
;                ENDS
		END     STARTX

end
