/*
   Einfache Flammen-Routine
*/

?resize TRUE

?include "VIDEO.H--"
?include "RANDOM.H--"
?include "KEYCODES.H--"
?include "DOS.H--"
?include "WRITE.H--"
?include "FLAT.H--"
?include "XMS.H--"

?define Width        280
?define Height       199
?define ScrollOfs    640
?define MaxHotSpots  32
?define HotSpotVal   255
?define FlatMemSize  0x100000

byte pal[768];
word VMem_a,VMem_b;           // VirtualVideoMem
word EMBHandle;
dword FlatMemStart,FlatMem;   // Aktuelle FlatMemAddresse
dword Screen1,Screen2;

void InitVGA ()
word i ;
{
	SETVIDEOMODE(0x13) ;
	SI=240;
	loop(SI)pal[SI-0x01]=0;
	i=8;
	loop(i){
		SI=i-1*3+2;
		DI=i+7*3+2;
		AX=i*2;
		BX=AX;
		CX=18-AX;
		BL+=2;
		pal[SI]=BL;
		pal[DI]=CL;
	}
	i=24 ;
	loop(i){
		SI=i+7*3;
		AX=i-1*63/23;
//		$push AX
		BL=AL;
		pal[SI]=BL;
		SI=i+31*3;
		pal[SI]=63;
		pal[SI+0x01]=BL;
		SI=i+55*3;
//		$pop AX
//		BL=AL;
		pal[SI]=63;
		pal[SI+0x01]=63;
		pal[SI+0x02]=BL;
	}
	SI=528;
	loop(SI)pal[SI+239]=63;
	SETVGADAC(0,,768,,,#pal);
}

void ClearBuffer()
{
	ES=VMem_a;
	ClearBuf();
	ES=VMem_b;
	ClearBuf();
}

void ClearBuf()
{
	DI=0;
	$CLD
	EAX=0;
	CX=16000;
	$REPZ
	$STOSD
}

void InitAll()
{
	@RANDOMIZE() ;
	VMem_a=GETMEM(4000);
	VMem_b=GETMEM(4000);
	ClearBuffer();
	IF(XMSallocateEMB(FlatMemSize)==0)@EXIT(-1);
	EMBHandle=DX;
	XMSlockEMB(EMBHandle);
	$SHL EDX,16
	DX=BX;
	FlatMemStart=EDX;
	InitVGA();
}

void CleanUp()
{
	SETVIDEOMODE(0x03);
	XMSunlockEMB(EMBHandle);
	XMSfreeEMB(EMBHandle);
	FREEMEM(VMem_a);
	FREEMEM(VMem_b);
}

void CalcLine(word yp)
{
	DI=320-Width+2>>1;
	AX=yp*320;
	DI+=AX;
	SI=DI;
	DI-=ScrollOfs;
	FS=VMem_a;
	ES=VMem_b;
	$CLD
	CX=Width-2;
	loop(CX){
		BX=0;
		AX=0;
		BL=FSBYTE[SI-1];
		$ADC AX,BX
		BL=FSBYTE[SI-321];
		$ADC AX,BX
		BL=FSBYTE[SI-320];
		$ADC AX,BX
		BL=FSBYTE[SI-319];
		$ADC AX,BX
		BL=FSBYTE[SI+1];
		$ADC AX,BX
		BL=FSBYTE[SI+321];
		$ADC AX,BX
		BL=FSBYTE[SI+320];
		$ADC AX,BX
		BL=FSBYTE[SI+319];
		$ADC AX,BX
		AX>>=3;
		IF(AL!=0)AL--;
		$STOSB
		SI++;
	}
}

void NewLine(word y)
{
	DI=320-Width+2>>1;
	AX=y*320;
	DI+=AX;
	SI=Width-2;
	ES=VMem_a;
	loop(SI){
		$CLD
		RAND();
		AX>>=12;
		$ADD AL,64
		$STOSB
	}
}

void SetHotSpots()
{
	RAND();
	BX=MaxHotSpots;
	$MUL BX
	DX++;
	SI=DX;
	ES=VMem_a;
	DI=320-Width+2>>1+63360;
	loop(SI){
		RAND();
		BX=Width-2;
		$MUL BX
		BX=DX;
		AL=HotSpotVal;
		ESBYTE[DI+BX]=AL;
		ESBYTE[DI+BX-1]=AL;
		ESBYTE[DI+BX-321]=AL;
		ESBYTE[DI+BX-320]=AL;
		ESBYTE[DI+BX-319]=AL;
		ESBYTE[DI+BX+1]=AL;
		ESBYTE[DI+BX+321]=AL;
		ESBYTE[DI+BX+320]=AL;
		ESBYTE[DI+BX+319]=AL;
	}
}

void CopyBuffer()
{
	ES=0xA000;
	$PUSH DS
	DS=VMem_b;
	DI=199-Height*320;
	SI=DI;
	CX=64000-DI>>2;
	$CLD
	$REPZ
	$MOVSD
	$POP DS
}

void DoTheScreen()
word y;
{
	NewLine(199);
	NewLine(198);
	NewLine(197);
	SetHotSpots();
	y=Height-1;
	loop(y)CalcLine(199-Height+y);
	CopyBuffer();
	VMem_a><VMem_b;
}

void TestFlatMem()
long y,dy;
{
	Screen1=FlatMemStart;
	Screen2=Screen1+64000;
	XMSlocalenableA20();
	ES=0xA000;
	DI=63999;
	GS=0;
	EAX=Screen2;
	CX=64000;
	loop(CX){
		BL=ESBYTE[DI];
		GSBYTE[EAX]=BL;
		EAX++;
		DI--;
	}
	CX=64000;
	DI=0;
	GS=DI;
	EAX=Screen1;
	loop(CX){
		BL=ESBYTE[DI];
		GSBYTE[EAX]=BL;
		EAX++;
		DI++;
	}
	ClearBuf();
	BIOSREADKEY();
	y=0;
	dy=320;
	do{
		IF(long y+dy>64000)-dy;
		IF(long y+dy<0)-dy;
		y+=dy;
		BX=16000;
		GS=0;
		EDX=Screen1+y;
		ECX=0xA0000;
		loop(BX){
			GSDWORD[ECX]=GSDWORD[EDX];
		  ECX+=4;
			EDX+=4;
		}
	}while(BIOSKEYCHECK()==FALSE);
	BIOSREADKEY();
}

main()
{
	IF(Enable_Flat()!=0)
			@WRITESTR("Processor already in V86-Mode or HIMES.SYS not installed!\n");
	ELSE{
		InitAll();
		do{
			DoTheScreen();
		}while(BIOSKEYCHECK()==FALSE);
		BIOSREADKEY() ;
		TestFlatMem();
		CleanUp();
	}
}
