*** empty log message ***
diff --git a/progs/ggi/asc-view.c b/progs/ggi/asc-view.c
new file mode 100644
index 0000000..16f53e5
--- /dev/null
+++ b/progs/ggi/asc-view.c
@@ -0,0 +1,353 @@
+/*
+    test program for the ggi-mesa driver
+
+    Copyright (C) 1997,1998  Uwe Maurer - uwe_maurer@t-online.de
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <GL/ggimesa.h>
+#include <ggi/ggi.h>
+#include <stdlib.h>
+
+ggi_visual_t vis,vis_mem;
+
+GGIMesaContext ctx;
+
+int screen_x=320,screen_y=200;
+ggi_graphtype bpp=GT_16BIT;
+
+//#define ZBUFFER
+
+//#define SMOOTH_NORMALS
+
+void Init()
+{
+	GLfloat h=(GLfloat)3/4;
+	GLfloat pos[4]={5,5,-20,0};
+	GLfloat specular[4]={.4,.4,.4,1};
+	GLfloat diffuse[4]={.3,.3,.3,1};
+	GLfloat ambient[4]={.2,.2,.2,1};
+
+	int err;
+
+	if (ggiInit()<0)
+	{
+		printf("ggiInit() failed\n");
+		exit(1);
+	}
+	ctx=GGIMesaCreateContext();
+	if (ctx==NULL)
+	{
+		printf("Can't create Context!\n");
+		exit(1);
+	}
+
+	vis=ggiOpen(NULL);
+	vis_mem=ggiOpen("display-memory",NULL);
+	if (vis==NULL || vis_mem==NULL)
+	{
+		printf("Can't open ggi_visuals!\n");
+		exit(1);
+	}	
+	err=ggiSetGraphMode(vis,screen_x,screen_y,screen_x,screen_y,bpp);
+	err+=ggiSetGraphMode(vis_mem,screen_x,screen_y,screen_x,screen_y,bpp);
+	if (err)
+	{
+		printf("Can't set %ix%i\n",screen_x,screen_y);
+		exit(1);
+	}
+
+	if (GGIMesaSetVisual(ctx,vis_mem,GL_TRUE,GL_FALSE)<0)
+	{
+		printf("GGIMesaSetVisual() failed!\n");
+		exit(1);
+	}
+
+	GGIMesaMakeCurrent(ctx);
+
+	glViewport(0,0,screen_x,screen_y);
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glFrustum(-1,1,-h,h,1,50);
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+	glTranslatef(0,0,-9);
+	glShadeModel(GL_FLAT);
+
+	glFrontFace(GL_CW);
+	glEnable(GL_CULL_FACE);
+	glEnable(GL_LIGHTING);
+	glEnable(GL_LIGHT0);
+	
+	glLightfv(GL_LIGHT0,GL_POSITION,pos);
+	
+	glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
+	glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
+	glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
+
+	#ifdef ZBUFFER
+		glEnable(GL_DEPTH_TEST);
+	#endif
+}
+
+
+#define MAX_VERTS 1000
+#define MAX_TRIS  2000
+#define MAX_LEN 1024
+#define MAX_F 100000000
+
+void LoadAsc(GLuint *list,char *file)
+{
+	FILE *fp;
+
+	GLfloat p[MAX_VERTS][3];
+	GLfloat normal[MAX_VERTS][3];
+	float ncount[MAX_VERTS];
+	int v[MAX_TRIS][3];
+	char line[MAX_LEN];
+	char *s;
+	int  i,j;
+	int verts,faces;
+	GLuint v0,v1,v2;
+	GLfloat n[3];
+	GLfloat len,k;
+	GLfloat min[3]={MAX_F,MAX_F,MAX_F};
+	GLfloat max[3]={-MAX_F,-MAX_F,-MAX_F};
+	char *coord_str[]={"X","Z","Y"};
+
+	fp=fopen(file,"r");
+	if (!fp) 
+	{
+		printf("Can't open %s!\n",file);	
+		exit(1);
+	}
+
+	while (strncmp(fgets(line,MAX_LEN,fp),"Tri-mesh",8)) ;
+	
+	s=strstr(line,":")+1;
+	verts=atoi(s);
+	s=strstr(s,":")+1;
+	faces=atoi(s);
+
+	if (verts>MAX_VERTS)	
+	{	
+		printf("Too many vertices..\n");
+		exit(1);
+	}
+	
+	while (strncmp(fgets(line,MAX_LEN,fp),"Vertex list",11)) ;	
+
+	for (i=0;i<verts;i++)
+	{
+		while (strncmp(fgets(line,MAX_LEN,fp),"Vertex",6)) ;	
+		for (j=0;j<3;j++)
+		{	
+			s=strstr(line,coord_str[j])+2;
+			k=atoi(s);
+			if (k>max[j]) max[j]=k;
+			if (k<min[j]) min[j]=k;
+			p[i][j]=k;
+		}
+		
+	}
+	len=0;
+	for (i=0;i<3;i++)
+	{
+		k=max[i]-min[i];
+		if (k>len) {len=k;j=i;}
+		n[i]=(max[i]+min[i])/2;
+	}
+
+	len/=2;
+
+	for (i=0;i<verts;i++)
+	{
+		for (j=0;j<3;j++)
+		{
+			p[i][j]-=n[j];
+			p[i][j]/=len;
+		}
+	}
+
+	*list=glGenLists(1);
+	glNewList(*list,GL_COMPILE);
+	glBegin(GL_TRIANGLES);
+
+	memset(ncount,0,sizeof(ncount));
+	memset(normal,0,sizeof(normal));
+
+	while (strncmp(fgets(line,MAX_LEN,fp),"Face list",9)) ;	
+	for (i=0;i<faces;i++)
+	{
+		while (strncmp(fgets(line,MAX_LEN,fp),"Face",4)) ;	
+		s=strstr(line,"A")+2;
+		v0=v[i][0]=atoi(s);
+		s=strstr(line,"B")+2;
+		v1=v[i][1]=atoi(s);
+		s=strstr(line,"C")+2;
+		v2=v[i][2]=atoi(s);
+		n[0]=((p[v1][1]-p[v0][1])*(p[v2][2]-p[v0][2]) 
+			- (p[v1][2]-p[v0][2])*(p[v2][1]-p[v0][1])); 
+		n[1]=((p[v1][2]-p[v0][2])*(p[v2][0]-p[v0][0]) 
+			- (p[v1][0]-p[v0][0])*(p[v2][2]-p[v0][2])); 
+		n[2]=((p[v1][0]-p[v0][0])*(p[v2][1]-p[v0][1]) 
+			- (p[v1][1]-p[v0][1])*(p[v2][0]-p[v0][0])); 
+		len=n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+		len=sqrt(len);
+		n[0]/=len;
+		n[1]/=len;
+		n[2]/=len;
+	#ifdef SMOOTH_NORMALS	
+		for (j=0;j<3;j++){
+			normal[v[i][j]][0]+=n[0];
+			normal[v[i][j]][1]+=n[1];
+			normal[v[i][j]][2]+=n[2];
+			ncount[v[i][j]]++;
+		}
+	#else
+		glNormal3fv(n);
+		for (j=0;j<3;j++)
+			glVertex3fv(p[v[i][j]]);
+	#endif
+	}
+
+	#ifdef SMOOTH_NORMALS
+		for (i=0;i<verts;i++) {
+			for (j=0;j<3;j++) {
+				normal[i][j]/=ncount[i];
+			}
+		}
+		for (i=0;i<faces;i++) {
+			for (j=0;j<3;j++) {
+				glNormal3f(normal[v[i][j]][0],
+					   normal[v[i][j]][1],
+					   normal[v[i][j]][2]);
+				glVertex3fv(p[v[i][j]]);
+			}
+		}
+	#endif
+
+	glEnd();
+	glEndList();
+	fclose(fp);
+}
+
+double Display(GLuint l,int *maxframes)
+{
+	int x,y;
+	GLfloat col[]={.25,0,.25,1};
+	int frames=0;
+	struct timeval start,stop;
+	double len;
+	GLfloat rotate=0;
+
+	gettimeofday(&start,NULL);
+
+
+	while(1)
+	{
+		glClearColor(0,0,0,0);
+		glClearIndex(0);
+
+		#ifdef ZBUFFER
+			glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+		#else
+			glClear(GL_COLOR_BUFFER_BIT);
+		#endif	
+
+		glPushMatrix();
+	
+		glRotatef(30,1,0,0);
+		glRotatef(rotate/10,0,0,1);
+		glTranslatef(-6,-4,0);
+		for (y=0;y<3;y++)
+		{
+			glPushMatrix();
+			for (x=0;x<5;x++)
+			{
+				glPushMatrix();
+				glRotatef(rotate,y+1,-x-1,0);
+
+				col[0]=(GLfloat)(x+1)/4;
+				col[1]=0;
+				col[2]=(GLfloat)(y+1)/2;
+				glMaterialfv(GL_FRONT,GL_AMBIENT,col);
+				glCallList(l);
+				glPopMatrix();
+				glTranslatef(3,0,0);
+			}
+			glPopMatrix();
+			glTranslatef(0,4,0);
+		}
+		glPopMatrix();
+		glFinish();
+
+		ggiPutBox(vis,0,0,screen_x,screen_y,ggiDBGetBuffer(vis,0)->read);
+		rotate+=10;
+		frames++;
+		if (frames==(*maxframes)) break;
+
+		if (ggiKbhit(vis))
+		{
+			*maxframes=frames;
+			break;
+		}
+	}
+
+	gettimeofday(&stop,NULL);
+	len=(double)(stop.tv_sec-start.tv_sec)+
+		(double)(stop.tv_usec-start.tv_usec)/1e6;	
+	return len;
+}
+
+
+int main(int argc,char **argv)
+{
+	GLuint l;
+	char *file;
+	int maxframes=0;
+	double len;
+
+	Init();
+
+	file=(argc>1) ? argv[1] : "asc/box.asc";
+	if (argc>2) maxframes=atoi(argv[2]);
+
+	if (argc==1)
+	{
+		printf("usage: %s filename.asc\n",argv[0]);
+	}
+
+	LoadAsc(&l,file);
+
+	len=Display(l,&maxframes);
+
+	printf("\ttime: %.3f sec\n",len);
+	printf("\tframes: %i\n",maxframes);
+	printf("\tfps: %.3f \n",(double)maxframes/len);
+
+	GGIMesaDestroyContext(ctx);
+	ggiClose(vis);
+	ggiClose(vis_mem);
+	ggiExit();
+	return 0;
+}
+