#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdlib.h>

#define NL 400
#define ui GLuint
#define uc GLubyte
#define z int

z  NP=100,  PS=10000, NE=15, NS=15;
float PSIZE=0.02, PL=0.2;

#define F3 for (l=0;l<3;l++)

#define E );


#define gE glEnable
#define gD glDisable
#define gMM glMatrixMode
#define gU glPushMatrix
#define gP glPopMatrix
#define gL glLoadIdentity
#define gT glTexParameteri
#define gC glTexCoord2f
#define g3 glVertex3f
#define g2 glVertex2f

#define R rand()

#define TW 256
#define TH 256

z w=640,h=480, i, j, l, cT, lT = 0, b[2] = {0, 1}, le[NL][4]; 
float eT, an=0, can = 0;

char str[1];

ui  fO, T[2];

uc let[][13]= {
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}};

void pS (char* s, z x, z y)
{
	glRasterPos2i(x,y E
	glPushAttrib (GL_LIST_BIT E
	glListBase(fO E
	glCallLists(strlen(s), 0x1401, (uc *) s E
	glPopAttrib ( E
}

void m (float e[NP][7], float* p, z t, z c[3])
{
	for (i=0; i<NP; i++)
		{
			F3
				e[i][l] += (float)(R%20)/*10*sin(R())*//PS;
			
			e[i][3] -= (float)eT*(R%10)/PS;
			if (e[i][3] <= 0)
			{
				e[i][3] = PL*(float)(R%10)/10;
				
				F3
					e[i][l] = p[l];

					F3
						e[i][l+4] = c[l];
			}
			
		}
}

void d(float e[NP][7])
{
		z mat [16];
		glDepthMask (0 E
		for (i=0; i<NP; i++)
		{
			glColor4f(e[i][4], e[i][5], e[i][6], e[i][3] E
				gU ( E
					glTranslatef (e[i][0], e[i][1], e[i][2] E
					
					glBegin (0x007 E 
						gC (0,0 E g3 (0,0,0 E
						gC (0, 1 E g3 (PSIZE, 0, 0 E
						gC (1, 1 E g3 (PSIZE, PSIZE, 0 E
						gC (1,0 E g3 (0, PSIZE, 0 E
					glEnd ( E
				gP ( E
				
			
		}
		glDepthMask (1 E
}

void VO()
{
	gMM(0x1701  E
	gU( E
	gL( E
	glOrtho( 0, 640 , 480, 0, -1, 1  E
	gMM( 0x1700  E 
	gU( E
	gL( E
}

void VP()
{
	gMM( 0x1701  E
	gP( E
	gMM(  0x1700  E 
	gP( E
}

void DB(z t, float inc)
{
	float sp = 0.0f, ai = 0.9f / t, a = 0.2f;

	gD(0x0C60 E
	gD(0x0C61 E
	gD(0x0B71 E
	glBindTexture(0x0DE1,T[0] E
	VO( E

	ai = a / t;
		

	glBegin(0x0007 E
		for (l = 0;l < t;l++)
		{
			glColor4f(1, 1, 1, a E
			gC(0+sp,1-sp E
			g2(0,0 E

			gC(0+sp,0+sp E
			g2(0,480 E

			gC(1-sp,0+sp E
			g2(640,480 E

			gC(1-sp,1-sp E
			g2(640,0 E

			sp += inc;
			a -= ai;
		}
	glEnd( E

	VP( E
	gE(0x0B71 E
}


z main (z argc, char** argv)
{
	GLUquadric* S = gluNewQuadric( E
	
	z c=0, pCol [NE][3];
	for (i=0;i<NL;i++)
	{
		le[i][0] = (R%26)+65;
		le[i][1] = c;
		le[i][2] = h;
		le[i][3] = (R%10 E
		c+=10;
		if (c>w)
			c=0;
	}
	
	float pTab [NE][NP][7], pPos [NE][3], pSP [NS][3];
	
	uc tI [2][TW][TH][4], k ;
	
	gluQuadricTexture (S,1 E
	
	bzero (&pTab, sizeof(float)*NE*NP*7 E
	bzero (&pPos, sizeof(float)*NE*3 E
	
	for (i=0;i < NS; i++)
	{
		F3
			pSP[i][l] = sin(R%10)*0.03*i;
		F3
			pPos[i][l] = pSP[i][l];
		F3
			pCol[i][l] = pSP[i][l]*100;
	}
	
	SDL_Event e;
		
	SDL_Init( 32  E
	SDL_GL_SetAttribute( 5, 1  E
	SDL_SetVideoMode(w, h, 24, 2 E
	
	for (i=0;i<TW;i++)
		for (j=0;j<TH;j++)
		{
			k = (uc)((((i&0x40)==0)^((j&0x40))==0))*255;
			F3
				tI[1][i][j][l] = k;
			tI[1][i][j][3] = (uc)255;
		}
	
	glPixelStorei (0x0CF5, 1 E
	
	fO = glGenLists (128 E
	for (i = 0, j = 'A'; i < 26; i++,j++)
	{
		glNewList(fO + j, GL_COMPILE E
		glBitmap(8, 13, 0, 2, 10, 0, let[i] E
		glEndList( E
	}

	for(i=0;i<2;i++)
	{
		glGenTextures(1, &T[i] E
		glBindTexture (0x0DE1, T[i] E
		gT (0x0DE1, 0x2801, 0x2601 E
		gT (0x0DE1, 0x2800, 0x2601 E
		glTexImage2D (0x0DE1, 0,0x1908, TW, TH, 0, 0x1908, 0x1401, tI[i] E 

	}

	float global_ambient[ 4 ]  = {0.2f, 0.2f,  0.2f, 1.0f}, 
	light0pos[ 4 ]          = {0.0f, 5.0f, 10.0f, 1.0f}, 
	light0ambient[ 4 ]      = {0.2f, 0.2f,  0.2f, 1.0f},
	light0diffuse[ 4 ]      = {0.3f, 0.3f,  0.3f, 1.0f},
	light0specular[ 4 ]     = {0.8f, 0.8f,  0.8f, 1.0f},         
	lmodel_ambient[ ]       = {0.2f, 0.2f,  0.2f, 1.0f};         


	glLightModelfv(0x0B53,lmodel_ambient E    
	glLightfv(GL_LIGHT0, GL_POSITION, light0pos E       
	glLightfv(GL_LIGHT0, GL_DIFFUSE, light0diffuse E
	gE(GL_LIGHTING E                                                                    
	gE(GL_LIGHT0 E                                                                         

	glClearColor( 0.1, 0.1, 0.1, 0.1  E
	glClearDepth( 1  E
	gE( 0x0B71 E
	gE( 0x0BE2 E 
	glBlendFunc( 0x0302, 1  E 
	gMM( 0x1701  E 
	gL(  E
	glViewport( 0, 0,w, h E
	gluPerspective( 45, (float)w/(float)h, 0.1, 100  E
	gMM( 0x1700  E 
	gL(  E
	
	while (!SDL_PollEvent (&e) || e.type != 2)
	{
		cT = SDL_GetTicks( E
		eT = (float)(cT- lT)/ 10;
		
		glClear( 0x00004000 | 0x00000100 E
		
		gL ( E
		
		gluLookAt (sin(can), cos(can), -0.4, 0, 0, 0, 0, 1, 0 E
		can += 0.01;
		
		glViewport (0, 0, TW, TH E
		for (l=0; l<NE; l++)
		{
			d(pTab[l] E
		}		
		gE (0x0DE1 E
		glBindTexture (0x0DE1, T[0] E
		glCopyTexImage2D(0x0DE1, 0, GL_LUMINANCE, 0, 0, TW, TH, 0 E
		glClearColor(0, .2,.2, 0.5f E
		glClear( 0x00004000 | 0x00000100 E
		glViewport(0 , 0,w, h E
		
		glBindTexture (0x0DE1, T[1] E
		for(i=0;i<NS;i++)
		{
			gU ( E
			glColor4f (pSP[i][0], pSP[i][1], pSP[i][2], 0.2 E
				glTranslatef (pSP[i][0], pSP[i][1], pSP[i][2] E
				gluSphere (S, 0.08, 15, 15 E
			gP ( E
		}
		
		gD (0x0DE1 E
		for (j=0;j<NE;j++)
		{
			m(pTab[j], pPos[j], eT, pCol[j] E
			pPos[j][0] = pSP[j][0] + 0.08*sinf(an E
			pPos[j][1] = pSP[j][1] + 0.08*cosf(an E
			d(pTab[j] E
		}
		
		an+=.09;
		
		gE (0x0DE1 E
		DB(b[0], .02f E
		
		gD (0x0DE1 E
		if ((b[0]+=b[1]) > 40/*(R()%40)*/)
			b[1] = -(R%10 E
		if (b[0] < 0)
			b[1] = (R%10 E
			
		VO( E
			glColor4f(1,1,1, 1 E
			for (i=0;i<NL;i++)
			{
				sprintf (str, "%c", le[i][0] E
				pS (str, le[i][1], le[i][2] E
				le[i][2] -= eT*(R%10 E
				le[i][3] -= eT*(R%10)/5;
				if (le[i][3] < 0)
				{
					le[i][3] = (R%50 E
					le[i][2] = h;
				}
			}
		VP( E
		
		lT = cT;
		SDL_GL_SwapBuffers( E
	}
}
