changeset 0:0e4f2da58161

Initial import.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 15 Mar 2013 05:00:01 +0200
parents
children bcdd2cc9f6e4
files 3x666.c 3xfont.h Makefile README config.h file_id.diz oxl.c oxl.h
diffstat 8 files changed, 1914 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/3x666.c	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,871 @@
+#include "math.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "fcntl.h"
+#include "unistd.h"
+#include "malloc.h"
+#include "time.h"
+#include "sys/time.h"
+
+#include "config.h"
+#include "oxl.h"
+#include "3xfont.h"
+
+#ifdef __linux__
+#include "linux/string.h"
+#else
+#include "string.h"
+#endif
+
+extern int TIKLGT;
+
+/** typedefs **/
+
+typedef struct { signed int x,y,z; } vec3d;
+
+/**/
+
+char *ruutu;
+int *mxbuf;
+
+int *ballz;
+
+/**************** tEXT dRAWiNG rOUTiNES **********
+
+bitmaps are for lamers :) let's use a little 12-segment calculator font...
+ascii chars 32..90, 16 bits per char unpacked -> 114 bytes for the whole
+font ;) let's credit karl/nooon for the original idea. */
+
+void drawseg(int y,int x,int w,int h)
+{
+	/* clip clip clip */
+	if(x+w>BUFW)w=BUFW-x;
+	if(x<0){w+=x;x=0;}
+	if(y+h>BUFH)h=BUFH-y;
+	if(y<0){h+=y;y=0;}
+	if(w>0)if(h>0){
+		char *b=ruutu+y*BUFW+x;
+		for(;h;h--){memset(b,122,w);b+=BUFW;}
+}	}
+
+void drawchar(int x,int y,int c,int xunit,int yunit)
+{	x-=xunit*2;
+	y-=yunit*3;
+	for(;;){
+	if(!c)break;
+	
+	if(c&1)drawseg(y,x+1,        xunit*2-2,yunit);
+	if(c&2)drawseg(y,x+1+xunit*2,xunit*2-2,yunit);
+	y++;
+
+	c>>=2;
+	if(!c)break;
+
+	if(c&1)drawseg(y,x,		   xunit,yunit*3-2);
+	if(c&2)drawseg(y,x+((xunit*3)>>1),xunit,yunit*3-2);
+	if(c&4)drawseg(y,x+xunit*3,xunit,yunit*3-2);
+
+	y+=yunit*2;
+	c>>=3;	
+}}
+
+void drawtxtscr(char*z)
+{
+	int x=BUFW>>4,y=BUFH>>3;
+	while(*z){
+		if(*z>=32){
+		  drawchar(x,y,phont[*z-32],BUFW/50,BUFW/80);
+		  x+=BUFW/10;
+		}else{x=BUFW>>4;y+=BUFW/10;}
+		z++;
+}	}
+
+
+void flashtxt(char*txt)
+{
+	int x=(BUFW>>1)-(strlen(txt)+1)*3*BUFW/80;
+	while(*txt){
+		drawchar(x,BUFH>>1,phont[*txt++-32],BUFW/50,BUFW/80);
+		x+=BUFW/10;}
+}
+
+/*************************** DA PHONGBALL HEAVEN **************
+
+A short course on phongball theory!
+
+A sphere: x^2+y^2+z^2=R^2
+
+Diffuse shading: intensity = dotproduct(surfacenormal,lightvector)
+
+(doing this for every drawn point of the surface is sometimes called
+phong shading even if the normals aren't actually interpolated)
+
+For a sphere, a normal vector at a point of the surface == constant *
+the coordinates of the point (if center == origo).
+
+Thus, the function for the intensity of a 2d-projected phongball can be
+stated as
+
+intensity(x,y) = l.x*x + l.y*y + l.z*z, z = sqrt(R^2-x^2-y^2)
+
+The first two muls can be eliminated easily. (and will be eliminated by
+a good compiler even if you are lazy)
+
+The third mul can be eliminated by approximating l.z*z with a function
+of the form f(x)=a*x^2+c. This approximation makes the ball look a bit
+"twisty" but who cares, it just looks damn cool ;) 
+
+***/
+
+#if BUFH<BUFW
+	#define maxR (BUFH>>1)
+#else
+	#define maxR (BUFW>>1)
+#endif
+
+struct{int *tab;signed int R;}balltab[50];
+
+void preball()
+{
+	unsigned int rR; signed int R;
+
+	for(rR=0;rR<48;rR++){
+		int R2,*d;signed int y;
+		R=(maxR*(rR+4))/52;
+		if(R<2)R=2;
+		R2=R*R;
+		balltab[rR].R=R;
+		d=balltab[rR].tab=malloc(R*2*sizeof(int)); 
+		for(y=-R+1;y<R-1;y++)*d++=sqrt(R2-y*y);
+	}	
+
+	balltab[49].R=balltab[48].R=balltab[47].R;
+	balltab[49].tab=balltab[48].tab=balltab[47].tab;
+}
+
+/**
+	The i386 innerloop compiled by gcc sucked a bit so here's another
+	one. Hope it runs faster :) I tried to optimize it for the 386,
+	maybe 486 (not pentium kos it suxx)
+
+**/
+
+inline void drawball_inloop
+  (char *d,int dotxyz,int ddot,int dddot,int x)
+{
+#if ASMLOOPS==386
+
+__asm__("
+
+	movl %%edx,%%ebp
+
+	movl %%ecx,%%eax
+	andb $3,%%al
+	je 1f
+	cmpb $1,%%al
+	je 2f
+	cmpb $2,%%al
+	je 3f
+
+4:	addl %%ebx,%%ebp
+	addl %%ebp,%%esi
+	shldl $16,%%esi,%%eax	
+	stosb
+
+3:	addl %%ebx,%%ebp
+	addl %%ebp,%%esi
+	shldl $16,%%esi,%%eax
+	stosb
+
+2:	addl %%ebx,%%ebp
+	addl %%ebp,%%esi
+	shldl $16,%%esi,%%eax
+	stosb
+
+1:	shrl $2,%%ecx
+	je 9f
+	jne 8f
+
+	.align 4
+
+8:	addl %%ebx,%%ebp
+	addl %%ebp,%%esi
+	
+	addl %%ebx,%%ebp
+	shldl $24,%%esi,%%edx
+	addl %%ebp,%%esi
+	shldl $24,%%esi,%%eax
+
+	addl %%ebx,%%ebp
+	movb %%dh,%%al
+	addl %%ebp,%%esi
+	stosw
+	shldl $24,%%esi,%%edx
+
+	addl %%ebx,%%ebp
+	addl %%ebp,%%esi
+	shldl $24,%%esi,%%eax	
+	movb %%dh,%%al		
+	
+	decl %%ecx
+	stosw	
+	jne 8b
+
+9:	
+"
+::	"c"(x),	
+	"D"(d),
+
+	"S"(dotxyz),
+	"d"(ddot),
+	"b"(dddot)
+
+:	"ax","bx","cx","dx","si","di","bp");
+
+#else
+
+	for(;x;x--){
+	dotxyz+=ddot;
+	ddot+=dddot;
+	*d++=dotxyz>>16;}
+
+#endif
+}
+
+void drawball(char *d,vec3d *l,int relR)
+{
+	int R=balltab[relR].R,*s=balltab[relR].tab;
+	
+	signed int doty=(-(R-1)*l->y);	
+	signed int y=R*2-2;
+
+	d+=(BUFW>>1)-R+((BUFH>>1)-R)*BUFW;
+
+	if(y)for(;y;y--){
+	int halfw=*s++;
+	if(halfw)
+		drawball_inloop(
+		d+R-halfw,
+	   	(doty-(l->x*halfw))<<8,	
+		(l->x+l->z)<<8,	
+		0-((l->z<<8)/halfw),
+		halfw<<1);
+	d+=BUFW;
+	doty+=l->y;
+}	}
+
+/* some extra for freaks: a plasma made with the phongball innerloop :)
+   looks ugly.
+
+void drawplasma(char *d,float t)
+{
+	int y=BUFH; float u=0,du=500/BUFH;
+
+	for(;y;y--){
+		drawball_inloop(d,
+			sin(t*0.02+0+u*0.033)*65536*256,
+			cos(t*0.04+1+u*0.022)*65536*4096/BUFW,
+			-2*cos(t*0.04+1+u*0.022)*65536*4096/(BUFW*BUFW), BUFW);
+		d+=BUFW;
+		u+=du;
+	}
+}
+*/
+
+/************************ oTHA FX ***************/
+
+void rotochess(char *d,int du,int dv,int iu,int iv)
+{
+	int hu=iu-(dv*(BUFH>>1))-(du*(BUFW>>1)),
+	    hv=iv+(du*(BUFH>>1))-(dv*(BUFW>>1));
+	    
+#if (ASMLOOPS==386) && (!(BUFW&3))
+
+__asm__("
+
+	movl %%eax,%%ebp
+
+1:	pushl %%ecx
+	pushl %%ebx
+	pushl %%edx
+
+	movl %0,%%ecx
+	jmp 0f
+
+	.align 4
+
+0:	addl %%ebp,%%ebx
+	movb %%bh,%%al
+	addl %%esi,%%edx
+	xorb %%dh,%%al
+	
+	addl %%ebp,%%ebx
+	movb %%bh,%%ah
+	addl %%esi,%%edx
+	xorb %%dh,%%ah	
+
+	addl %%ebp,%%ebx
+	andl $0xb1b1,%%eax
+	stosw
+	movb %%bh,%%al
+	addl %%esi,%%edx
+	xorb %%dh,%%al
+
+	addl %%ebp,%%ebx
+	movb %%bh,%%ah
+	addl %%esi,%%edx
+	xorb %%dh,%%ah
+	andl $0xb1b1,%%eax
+
+	decl %%ecx
+	stosw
+	jne 0b
+	
+	popl %%edx
+	popl %%ebx
+	popl %%ecx
+	
+	subl %%ebp,%%edx
+	addl %%esi,%%ebx
+	
+	decl %%ecx
+	jne 1b
+"
+::	"m"(BUFW/4),
+
+	"c"(BUFH),	// ecx == x
+	"D"(d),	// edi == *d
+	
+	"b"(hu),"a"(du),
+	"d"(hv),"S"(dv)
+	
+:	"ax","bx","cx","dx","si","di","bp");
+	d+=BUFW;
+#else
+	int y;
+	for(y=BUFH;y;y--){
+	  {register int u=hu,v=hv,x=BUFW;
+	  for(;x;x--){
+	  u+=du;v+=dv;*d++=((u^v)>>8)&0xb1;}}
+	hu+=dv;hv-=du;}	  
+#endif
+}
+
+/***************************************************************/
+
+rgb pal[256],pal2[256];
+void setpal()	
+{
+	int i,a=3,b=0;
+	for(i=255;i;i--){
+		rgb*d=&pal[(i+128)&255];
+		d->r=(abs(i-140)>>a)&255;
+		d->g=((abs(i-128)>>b)&255)^1;
+		d->b=(abs(i-96)>>b)&255;
+		if(i==128){a=0;b=1;}
+	}
+	oxl_setpalette(pal);
+}
+
+void unitvec(vec3d *v,float a,float b,float c,float m)
+{
+	float cam=cos(a)*m,sam=sin(a)*m,sbcam=sin(b)*cam;
+	
+	v->x=cos(b)*cam;
+	v->y=cos(c)*sam-sin(c)*sbcam;
+	v->z=cos(c)*sbcam+sin(c)*sam;
+}
+
+/************************* MUSiC cODE **************************/
+
+#if AUDIO
+
+/* This table was ripped (and reduced and rudely integerized) from the
+   Maube tracker by K .. keep on the good work man! ;) */
+
+const int noterate[3*12] = {     
+     1000, 1059, 1122, 1189, 1259, 1334,
+     1414, 1498, 1587, 1681, 1781, 1887,
+     
+     2000, 2118, 2244, 2378, 2519, 2669,
+     2828, 2996, 3174, 3363, 3563, 3775,
+     
+     4000, 4237, 4489, 4756, 5039, 5339,
+     5656, 5993, 6349, 6727, 7127, 7550
+};
+
+/*	64 bytes of pure musical power ;)  
+	Originally composed with Scream Tracker.  */
+
+const char basstrak[32]={
+	12,0, 24,12,
+	12,24,12,24,
+	12,0, 24,12,
+	12,24,12,24,
+	15,0, 27,15,
+	15,27,15,27,
+	14,0, 26,14,
+	15,27,17,29};
+
+const char melody[32]={
+	24,12,19,15,
+	24,0, 19,0,
+	24,12,19,15,
+	24,0, 15,19,
+	15,19,15,19,
+	22,0, 15,19,
+	14,17,21,14,
+	22,17,17,22};
+
+signed int*drum0,*drum1;
+
+void audio_precalcs()
+/* sampling sucks! */
+{
+	int drumlgt=TIKLGT*ROWTIX*4;
+	int *d=drum0=malloc(drumlgt*sizeof(int)),
+	    *e=drum1=malloc(drumlgt*sizeof(int)),i,
+		 vol=24680,dvol=35000/(float)drumlgt;
+	int o=0,oo=0;float a=0,da=386/(float)drumlgt,dda=da/(float)drumlgt;
+
+	printf("aCtIvATiNg 303 eMuLAtOR\n");
+	
+	for(i=drumlgt;i;i--){
+		int u;
+		
+		o=(o>>1)+(rand()%vol)-(rand()%vol);		
+		oo=(oo*2+((rand()%vol)-(rand()%vol)))/3;
+
+		o*=sin(a);oo*=sin(a);
+
+		u=o*2;if(u<-65535)u=-65535;if(u>65535)u=65535;
+		*d++=(vol*sin((a/2)+((float)u)/80000));
+		*e++=(vol*sin(a+((float)oo)/60000));
+
+		a+=da;da-=dda;vol-=dvol;
+}	}
+
+int*audio_mix(void)
+/* mixes the next row of music into b */
+{
+	static int rowno=0;
+	static signed int delta=-5;
+	static char ismelody=0,silend=0;
+	
+	int rowlgt=TIKLGT*ROWTIX,i;
+	int *d=mxbuf,note;
+	
+		/* BASS (sawtooth ofcoz) */
+
+	*d++=rowlgt;
+	
+	note=basstrak[(rowno>>1)&31];	
+	
+	if(!note)note=basstrak[((rowno>>1)&31)-1];
+		else if(rowno&1)note=0;
+	if((rowno&3)==3)note=0;
+	if(note){
+		int ps=16384,dps;
+		note+=delta;
+		dps=((noterate[note]<<10)/AUFREQ);
+		for(i=rowlgt;i;i--){
+			*d++=ps;ps=(ps+dps)&32767; }
+	}else
+		for(i=rowlgt;i;i--)*d++=16384;
+
+		/* MELODY (sawtooth as well :) */
+
+	if(!(silend&&((rowno&63)>47))){
+
+	if(ismelody){
+	d=mxbuf+1;
+	if(rowno&1)note=0;else note=melody[(rowno>>1)&31];
+	if(note){
+		int ps=16384,dps;	/* this loop is different */
+		note+=delta;
+		dps=((noterate[note]<<12)/AUFREQ);
+		for(i=rowlgt;i;i--){
+ 			*d+++=ps;ps=(ps+dps)&32767;}
+ 	}}
+		/* DRUMS (rave on!!!) */
+
+	{
+		int *s=drum1;d=mxbuf+1;
+		if(rowno&4)s=drum0;
+		s+=(rowno&3)*rowlgt;
+		
+		for(i=rowlgt;i;i--)*d+++=*s++;
+	}
+	}
+		/* PATTERN SHIFT */
+
+	rowno++;
+	
+	/* no switch+case? just check out how gcc handles them!  
+	   it's 1024+ bytes for every phukken switch statement!	   
+	   in this case we can prefer size to speed, can't we? */
+
+	if(!(rowno&63)){
+		int r=rowno>>6;
+		if(r==2)delta=0;
+		if(r==4)ismelody=1;
+		if((r==6)||(r==10))delta=5;
+		if((r==7)||(r==11))silend=1;
+		if(r==8)delta=silend=0;
+		if(r==12){rowno=ismelody=silend=0;delta=-5;}
+	}
+	return mxbuf;	
+}
+
+#endif
+
+/**************** tEXT gENERATORS eTC ***************/
+
+char skrtxt[]={
+"         HI THERE !  THIS IS THE FIRST OCSA RELEASE FOR LINUX !  "
+"IT'S A STUPID INTRO CALLED 3X666 !          " };
+
+void plainscroll(int t)
+#define CHTIME 16
+#define CHPSCR 8
+{	
+	int chno=t/CHTIME;
+	int x=0-((t%CHTIME)*(BUFW/CHPSCR))/CHTIME;
+	int h=(abs((t%48)-24)*BUFH)/256,i;
+	char*c=skrtxt+chno;
+
+	for(i=0;i<CHPSCR+1;i++){
+		drawchar(x,(BUFH*3)/4,phont[*c++-32],BUFW/(6*CHPSCR),h);
+		x+=BUFW/CHPSCR;
+}	}
+
+char*lyrix(void)
+{
+	static int phinext=0,philast;
+	int phiwsty;
+	char*phiword;
+
+	phiwsty=phinext;
+
+if(!phiwsty){
+	if(!(rand()&3))phiwsty=13;
+	else phiwsty=1+(rand()&1);
+}
+if(phiwsty==1){
+	char *w[]={"HERE","THERE","NOW","TOMORROW","TODAY","NEVER"};
+	phiword=w[rand()%6];
+	if(rand()&1)phinext=2;else phinext=12;
+}else
+if(phiwsty==2){
+	char nx[]={5,10,7,3,11};
+	philast=rand()&1;
+	if(!philast)phiword="YOU";else phiword="I";
+	phinext=nx[rand()%5];
+}else
+if(phiwsty==3){
+	char *w[]={"DON'T","CAN'T","WON'T","COULDN'T"};
+	phiword=w[rand()%4];phinext=7+(rand()&4);
+}else
+if(phiwsty==4){
+	if(rand()&1)phiword="YOU";else phiword="ME";
+	if(rand()&1)phinext=6;else if(rand()&1)phinext=0;else phinext=11;
+}else
+if(phiwsty==5){
+	if(philast)phiword="AM";else phiword="ARE";
+	if(rand()&1)phinext=6;else phinext=12+(rand()&1);
+}else
+if(phiwsty==6){
+	char *w[]={"FALLING","THINKING","DREAMING","CRYING",
+	"LYING","REACHING","BREATHING","BURNING","RUNNING"};
+	phiword=w[rand()%9];
+	if(rand()&1)phinext=9;else if(rand()&1)phinext=0;else phinext=13;
+}else
+if(phiwsty==7){
+	char nx[]={8,4,12};
+	if(rand()&1)phiword="NEED";else phiword="WANT";
+	phinext=nx[rand()%3];
+}else
+if(phiwsty==8){phiword="TO";phinext=11;
+}else
+if(phiwsty==9){
+	char *w[]={"DOWN","OFF","OUT","UP","ABOUT"};
+	phiword=w[rand()%5];
+	if(rand()&1)phinext=rand()&4;else phinext=12+(rand()&1);
+}else
+if(phiwsty==10){
+	char *w[]={"CAN","COULD","WOULD","MAY","MIGHT"};
+	phiword=w[rand()%5];
+	if(rand()&1)phinext=11;else phinext=12;
+}else
+if(phiwsty==11){
+	char *w[]={"SEE","HEAR","FEEL","THINK"};
+	phiword=w[rand()%4];
+	if(rand()&1)phinext=12;else phinext=rand()&4;
+}else
+if(phiwsty==12){
+	char *w[]={"WHAT","SOMETHING","NOTHING","THINGS","WHATEVER"};
+	phiword=w[rand()%5];phinext=2;
+}else
+if(phiwsty==13){
+	phiword="THE";phinext=14;
+}else{
+	char*w[]={"WAY","EYES","WORLD","ROBOT","FREEDOM","HATE"};
+	phiword=w[rand()%6];phinext=0;	
+}
+return phiword;
+}
+
+char*dotxtscr(void)
+{
+	static int cnt=0;
+	cnt++;
+	if(cnt==1)
+	return
+		"WHERES THE\n"
+		"DESIGN?\n\n"
+		"WHERES THE\n"
+		"ATTITUDE?!";
+	
+	if(cnt==2)
+	return
+		"NOTHING\n"
+		"HAPPENED\n"
+		"IN 1997";
+
+	if(cnt==3)
+	return
+		"PERHAPS\n"
+		"IT IS TIME\n"
+		"FOR A NEW\n"
+		"PROPHECY?";
+
+	if(cnt==4)
+	return
+		"IN 1998,\n"
+		"SCENE WILL\n"
+		"DIE !!!!!";
+
+	if(cnt==5)
+	return		
+		"PHONGBALLS\n"
+		"WILL\n"
+		"INVADE\n"
+		"THE WORLD";
+
+	if((cnt==6)||(cnt==7))
+	return
+		"HALUU OLLA\n"
+		"APPELSIINI";
+		
+	return NULL;
+}
+
+const char*endscroll=
+"THAT'S ALL
+FOLKS !
+
+ALL CODING +
+COMPOSING
+BY VIZNUT !
+
+WHAT A
+MARVELOUS
+PALETTE !
+WHAT A
+SUPERB TUNE !
+
+BUT IT'S ALL
+BELOW 10 KB
+AND RUNS
+SMOOTHLY ON
+A 386
+
+GREETINGS TO
+ALL THE
+LINUX SCENE !
+
+LET'S MAKE
+THIS WORLD A
+BETTER PLACE
+TO LIVE IN !
+
+THIS IS JUST
+A PIECE OF
+SHITTY CODE
+BUT IT'S ALL
+YOURS !
+
+RIP OFF
+EVERYTHING !
+USE IT FOR
+SOMETHING
+CREATIVE !
+"
+
+"\n\n\nOCSA 1998";
+
+void doendscroll(int t)
+{
+	const char *s=endscroll;
+	int y=BUFH-(BUFH*t/512),x=BUFW/24;
+
+	while(*s){
+		if(*s<32){x=BUFW/24;y+=BUFH/8;}else{
+		if(y>=0-(BUFH/8))if(y<BUFH){
+			drawchar(x,y,phont[*s-32],BUFW/60,BUFH/60);
+			x+=BUFW/13;}
+		}
+	s++;}
+}
+
+/********************** tHA kORE bEGiNS *********************/
+
+#define BLACKBG   1
+#define FLASHBG   2
+#define OCSALOGO  4
+#define SCROLL0   8
+#define BALLIE    16
+#define BALLJUMPS 32
+#define COUNTAH   64
+#define CHESSBG   128
+#define PLASMABG  256
+#define FLASHTXT  512
+#define TXTSCR    1024
+#define ENDSCR    2048
+#define DEMOEND   4096
+
+const short dezign[]={
+	0,	 BLACKBG|OCSALOGO|SCROLL0,
+	256,FLASHBG|BALLIE|BALLJUMPS|COUNTAH,
+	384,BLACKBG|BALLIE|BALLJUMPS|COUNTAH|OCSALOGO,
+	400,BLACKBG|BALLIE|COUNTAH|OCSALOGO,
+	416,BLACKBG|BALLIE,
+	448,BLACKBG|BALLIE|TXTSCR,
+	512,CHESSBG|BALLIE|BALLJUMPS|TXTSCR,
+	576,CHESSBG|BALLIE|BALLJUMPS|TXTSCR,
+	640,CHESSBG|BALLIE|BALLJUMPS|TXTSCR,
+	704,CHESSBG|BALLIE|BALLJUMPS|TXTSCR,
+	768,FLASHBG|FLASHTXT,	
+	896,FLASHBG|FLASHTXT|TXTSCR,
+	962,FLASHBG|FLASHTXT|TXTSCR|BALLIE|BALLJUMPS,
+	1024,BLACKBG|BALLIE|ENDSCR,
+	1152,CHESSBG|BALLIE|BALLJUMPS|ENDSCR,
+	1344,FLASHBG|BALLIE|BALLJUMPS|ENDSCR,
+ 	1536,DEMOEND
+};
+
+
+/* don't look at the rest of the code, it just sucks :) */
+
+void main(void)
+{
+	vec3d joo;
+
+	int flagz=0;const short*dez=dezign;
+	char *phiword=NULL,*dizainword=NULL;int flixtim=0;
+
+	ruutu=malloc(BUFH*BUFW*sizeof(char));	
+	preball();
+
+	srand((int)time(NULL));
+
+#define MAXROWLGT TIKLGT*ROWTIX
+ 
+#if AUDIO!=0
+	oxl_init_audio(ROWTIX);
+	TIKLGT=AUFREQ/DEMOHZ;
+	mxbuf=malloc(MAXROWLGT*sizeof(int));
+	audio_precalcs();
+#endif
+
+	oxl_init_video();
+	oxl_init_timer();
+
+	setpal();
+	
+	for(;;){
+	int t=oxl_timer();
+
+	while((t/ROWTIX>=*dez)&&(!(flagz&DEMOEND)))
+		{dez++;flagz=*dez++;
+		 if(flagz&FLASHTXT)flixtim=*(dez-2); 
+		 if(flagz&TXTSCR)dizainword=dotxtscr();
+		 }
+	if(flagz&FLASHTXT)
+	  while((t/ROWTIX)>=flixtim){phiword=lyrix();flixtim+=4;}
+
+	if(flagz&DEMOEND)break;
+
+	if(flagz&BLACKBG)memset(ruutu,0,BUFH*BUFW);else
+	if(flagz&FLASHBG)
+		{ unsigned char col=130+(t%48)*2;
+		#if ASMLOOPS==386
+	/* the original asm/string.h by linus does this with stosb, so */		
+	__asm__("rep;stosl"::"D"(ruutu),"c"((BUFH*BUFW)>>2),
+	"a"(col|(col<<8)|(col<<16)|(col<<24)):"ax","cx","di");
+		#else
+		memset(ruutu,col,BUFH*BUFW);
+		#endif
+	}
+
+	if(flagz&CHESSBG){int zoom=((10+abs(((t>>1)%96)-48))*4096/BUFW);
+		rotochess(ruutu,
+		sin(t*0.03)*zoom,cos(t*0.03)*zoom,0,0);}
+
+/*	if(flagz&PLASMABG) drawplasma(ruutu,t); */
+
+	if(flagz&OCSALOGO){
+		#define U (BUFW/40)
+			drawchar(U*6,U*4,phont['O'-32],U+U*sin(t*0.10+3),U);
+			drawchar(U*14,U*4,phont['C'-32],U,U+U*sin(t*0.11+3));
+			drawchar(U*22,U*4,phont['S'-32],U,U+U*sin(t*0.12+3));		
+			drawchar(U*30,U*4,phont['A'-32],U+U*sin(t*0.13+3),U);
+		#undef U
+	}
+	
+	if(flagz&SCROLL0)plainscroll(t);
+	
+	if(flagz&BALLIE){
+		int zoom;
+		if(flagz&BALLJUMPS)zoom=abs((t%96)-48);else zoom=47;
+		if(zoom<0)zoom=0;else if(zoom>47)zoom=47;
+		
+		unitvec(&joo,0.038*t,0.023*t,0.011*t,32000/balltab[zoom].R);
+		joo.z<<=1;
+		
+		drawball(ruutu,&joo,zoom);
+	}
+
+	if(flagz&FLASHTXT)flashtxt(phiword);
+	if(flagz&TXTSCR)if((t/ROWTIX)&2)drawtxtscr(dizainword);
+
+	if(flagz&ENDSCR)doendscroll(t-1024*ROWTIX);
+
+	#define U (BUFW/40)
+	if(flagz&COUNTAH)
+	  {int n=((t*50/48)-256*6);
+	  int dis=(rand()%U)>>1;
+	  if(n>666)n=666;
+	  if(n>600){
+	  	drawchar(U*12+dis,(BUFH>>1)+dis+U*6,phont['X'-32],U,U);
+	  	drawchar(U*22+dis,(BUFH>>1)+dis+U*6,phont['3'-32],U,U);}		
+		drawchar(U*28+dis,BUFH>>1,phont[16+(n%10)],U,U);n/=10;
+		drawchar(U*18+dis,BUFH>>1,phont[16+(n%10)],U,U);n/=10;
+		drawchar(U*8+dis,BUFH>>1,phont[16+(n%10)],U,U);n/=10;
+	}	
+	#undef U
+	
+	/* blitzz */
+	
+		oxl_doframe(ruutu);
+	#if AUDIO!=0
+		oxl_doaudio(audio_mix);
+	#endif
+		while(t==oxl_timer()){
+		#if SLEEPY
+			usleep(250000/DEMOHZ);
+		#endif
+		}
+	}
+	oxl_end();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/3xfont.h	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,434 @@
+/*
+The font structure: think it out as a segmented lcd display:
+	
+	 aa bb
+	c  d  e
+	c  d  e
+	 ff gg
+	h  i  j
+	h  i  j
+	 kk ll
+*/   
+    
+#define Q(a,b,c,d,e,f,g,h,i,j,k,l) \
+        a+(b<<1)+(c<<2)+(d<<3)+(e<<4)+(f<<5)+(g<<6)+ \
+        (h<<7)+(i<<8)+(j<<9)+(k<<10)+(l<<11)
+
+short phont[]={
+
+Q(	/* space 32 */
+ 0,0,
+0,0,0,
+ 0,0,
+0,0,0,
+ 0,0 ),
+
+Q(	/* ! 33 */
+  1,1,
+ 1,0,1,
+  1,1,
+ 0,0,0,
+  1,1 ),
+
+Q(	/* " 34 */
+ 0,0,
+1,0,1,
+ 0,0,
+0,0,0,
+ 0,0 ),
+ 
+Q(	/* # 35 .. let's give up :) */
+ 1,1,
+1,1,1,
+ 1,1,
+1,1,1,
+ 1,1 ),
+ 
+Q(	/* $ 36 */
+ 1,1,
+1,1,0,
+ 1,1,
+0,1,1,
+ 1,1 ),
+
+Q(	/* % 37 */
+ 1,0,
+0,0,1,
+ 1,1,
+1,0,0,
+ 0,1 ),
+ 
+Q(	/* ~ 38	not ascii */
+ 0,1,
+1,0,1,
+ 1,0,
+0,0,0,
+ 0,0 ),
+ 
+Q(	/* ' 39 */
+ 0,0,
+0,0,1,
+ 0,1,
+0,0,0, 
+ 0,0 ),
+ 
+Q(	/* ( 40 */
+ 1,1,
+1,0,0,
+ 0,0,
+1,0,0,
+ 1,1 ),
+ 
+Q(	/* ) 41 */
+ 1,1,
+0,0,1,
+ 0,0,
+0,0,1,
+ 1,1 ),
+ 
+Q(	/* * 42 */
+ 0,0,
+1,1,1,
+ 1,1,
+1,1,1,
+ 0,0 ),
+ 
+Q(	/* + 43 */
+ 0,0,
+0,1,0,
+ 1,1,
+0,1,0,
+ 0,0 ),
+
+Q(	/* , 44 */
+ 0,0,
+0,0,0,
+ 0,0,
+0,0,1,
+ 0,1 ),
+ 
+Q(	/* - 45 */
+ 0,0,
+0,0,0,
+ 1,1,
+0,0,0,
+ 0,0 ),
+ 
+Q(	/* . 46 */
+ 0,0,
+0,0,0,
+ 0,0,
+0,0,0,
+ 1,1 ),
+
+Q(	/* / 47 */
+ 0,0,
+0,0,1,
+ 1,1,
+1,0,0,
+ 0,0 ),
+ 
+Q(	/* 0 48 */
+ 1,1,
+1,0,1,
+ 0,0,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* 1 49 */
+ 0,0,
+0,1,0,
+ 0,0,
+0,1,0,
+ 0,0 ),
+ 
+Q(	/* 2 50 */
+ 1,1,
+0,0,1,
+ 1,1,
+1,0,0,
+ 1,1 ),
+ 
+Q(	/* 3 51 */
+ 1,1,
+0,0,1,
+ 0,1,
+0,0,1,
+ 1,1 ),
+ 
+Q(	/* 4 52 */
+ 0,0,
+1,0,1,
+ 1,1,
+0,0,1,
+ 0,0 ),
+
+Q(	/* 5 53 */
+ 1,1,
+1,0,0,
+ 1,1,
+0,0,1,
+ 1,1 ),
+ 
+Q(	/* 6 54 */
+ 1,1,
+1,0,0,
+ 1,1,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* 7 55 */
+ 1,1,
+1,0,1,
+ 0,0, 
+0,0,1,
+ 0,0 ),
+ 
+Q(	/* 8 56 */
+ 1,1,
+1,0,1,
+ 1,1,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* 9 57 */
+ 1,1,
+1,0,1,
+ 1,1,
+0,0,1,
+ 1,1 ),
+ 
+Q(	/* : 58 */
+ 1,1,
+0,0,0,
+ 0,0,
+0,0,0,
+ 1,1 ),
+ 
+Q(	/* ; 59 */
+ 1,1,
+0,0,0,
+ 0,0,
+0,0,1,
+ 0,1 ),
+ 
+Q(	/* < 60 */
+ 0,1,
+0,1,0,
+ 1,0,
+0,1,0,
+ 0,1 ),
+ 
+Q(	/* = 61 */
+ 1,1,
+0,0,0,
+ 0,0,
+0,0,0,
+ 1,1 ),
+ 
+Q(	/* > 62 */
+ 1,0,
+0,1,0,
+ 0,1,
+0,1,0,
+ 1,0 ),
+ 
+Q(	/* ? 63 */
+ 1,1,
+0,0,1,
+ 1,1,
+0,0,0,
+ 1,1 ),
+  
+Q(	/* @ 64 */
+ 1,1,
+1,1,1,
+ 0,1,
+1,1,1,
+ 1,0 ),
+ 
+Q(	/* A 65 */
+ 1,1,
+1,0,1,
+ 1,1,
+1,0,1,
+ 0,0 ),
+ 
+Q(	/* B 66 */
+ 1,0,
+1,1,0,
+ 1,1,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* C 67 */
+ 1,1,
+1,0,1,
+ 0,0,
+1,0,0,
+ 1,1 ),
+ 
+Q(	/* D 68 */
+ 0,0,
+0,0,1,
+ 1,1,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* E 69 */
+ 1,1,
+1,0,0,
+ 1,0,
+1,0,0,
+ 1,1 ),
+ 
+Q(	/* F 70 */
+ 1,1,
+1,0,0,
+ 1,0,
+1,0,0,
+ 0,0 ),
+ 
+Q(	/* G 71 */
+ 1,1,
+1,0,0, 
+ 0,1,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* H 72 */
+ 0,0,
+1,0,1,
+ 1,1,
+1,0,1,
+ 0,0 ),
+ 
+Q(	/* I 73 */
+ 1,1,
+0,1,0,
+ 0,0,
+0,1,0,
+ 1,1 ),
+ 
+Q(	/* J 74 */
+ 0,0,
+0,0,1,
+ 0,0,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* K 75 */
+ 0,1,
+1,1,0,
+ 1,1,
+1,0,1,
+ 0,0 ),
+
+Q(	/* L 76 */
+ 1,0,
+1,0,0,
+ 0,0,
+1,0,0,
+ 1,1 ),
+
+Q(	/* M 77 */
+ 1,1,
+1,1,1,
+ 0,0,
+1,0,1,
+ 0,0 ),
+
+Q(	/* N 78 */
+ 1,1,
+1,0,1,
+ 0,0,
+1,0,1,
+ 0,0 ),
+ 
+Q(	/* O 79 */
+ 1,1,
+1,0,1,
+ 0,0,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* P 80 */
+ 1,1,
+1,0,1,
+ 1,1,
+1,0,0,
+ 0,0 ),
+ 
+Q(	/* Q 81 */
+ 1,1,
+1,0,1,
+ 0,0,
+1,1,1,
+ 1,1 ),
+ 
+Q(	/* R 82 */
+ 1,1,
+1,0,1,
+ 1,1,
+1,1,0,
+ 0,1 ),
+ 
+Q(	/* S 83 */
+ 1,1,
+1,0,0,
+ 1,1,
+0,0,1,
+ 1,1 ),
+ 
+Q(	/* T 84 */
+ 1,1,
+1,1,1,
+ 0,0,
+0,1,0,
+ 0,0 ), 
+
+Q(	/* U 85 */
+ 0,0,
+1,0,1,
+ 0,0,
+1,0,1,
+ 1,1 ),
+ 
+Q(	/* V 86 */
+ 0,0,
+1,0,1,
+ 1,0,
+0,1,1,
+ 0,1 ),
+ 
+Q(	/* W 87 */
+ 0,0,
+1,0,1,
+ 0,0,
+1,1,1,
+ 1,1 ),
+
+Q(	/* X 88 */
+ 0,0,
+0,1,1,
+ 1,1,
+1,1,0,
+ 0,0 ),
+
+Q(	/* Y 89 */
+ 0,0,
+1,0,1,
+ 1,1,
+0,1,0,
+ 0,0 ),
+ 
+Q(	/* Z 90 */
+ 1,1,
+0,0,1,
+ 1,1,
+1,0,0,
+ 1,1 ),
+  
+}; 
+
+#undef Q
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,41 @@
+# mAKEFiLE fOR 3x666 bY oCSA
+
+# Choose either vga or X11
+VIDEO = X11
+
+# 1 = /dev/dsp a.k.a OpenSoundSystem; 0 = nosound
+AUDIO = 0
+
+# Ok, next check out config.h!
+
+## ## ## ##
+
+CC = gcc
+
+COPT = -O9 -funroll-loops -fomit-frame-pointer
+
+# If you prefer size to speed, use of the below COPTs:
+# i386 size
+#COPT = -O2 -m386 -fomit-frame-pointer -malign-functions=0 -malign-loops=0 -malign-jumps=0
+# generic size
+#COPT = -O2
+
+CFLAGS = -g -Wall -DVIDEO=$(VIDEO) -DAUDIO=$(AUDIO) 
+LIBS   = -l$(VIDEO) -lm
+
+# You may want to check out if these dirs are right.
+INCDIR = 
+LIBDIR = -L/usr/X11R6/lib
+
+# These are for sun.
+#INCDIR = -I/usr/openwin/include
+#LIBDIR = -L/usr/openwin/lib
+
+3x666: 3x666.o oxl.o
+	$(CC) 3x666.o oxl.o -s -o 3x666 $(LIBDIR) $(LIBS)
+
+oxl.o: oxl.c config.h
+	$(CC) oxl.c -c -o oxl.o $(COPT) $(CFLAGS) $(INCDIR)
+
+3x666.o: 3x666.c oxl.h config.h 3xfont.h
+	$(CC) 3x666.c -c -o 3x666.o $(COPT) $(CFLAGS) $(INCDIR)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,57 @@
+***************************
+*
+** How do I compile this???
+
+Check out the makefile (VIDEO and AUDIO) and config.h (BUFW and BUFH)
+and change the values appropriately :) Then type make.
+
+You need an X window system or svgalib, 8 bits per pixel. You may need
+to change the lib setting in the makefile to point to your Xlib dir.
+
+Tested on i386linux, aix (ibm rs/6000) and sun. Audio only works on linux,
+freebsd etc.
+
+**********************************************************************
+* 
+** I only have an Alpha, is it enough for watching this demo???
+
+This phukken multimedia show runs reasonably smoothly on an 386 machine
+(about 20x faster than most of today's msdos intros ;) in a 320x200
+window.
+
+The palette is ugly, the effects lousy. Hope you still enjoy it :)
+
+*************
+*
+** Credits **
+
+Almost everything done by Viznut this time. Greetings to all
+betatesters etc :)
+
+*******************
+*
+** To contact ocsa
+
+vheikkil@hytti.uku.fi
+www.hytti.uku.fi/~vheikkil/
+
+Member applications are not forbidden :)
+
+***************
+*
+** The binary
+
+The packet also contains a precompiled executable for dummies only.
+(Linux i386 shared elf svgalib devdsp 320x200x256, run as root)
+
+You should know it is very rude to spread suidroot binaries like this
+so if you care about the security of your system, just delete the bin
+and forget it!
+
+****************
+*
+** Copyright??
+
+Who cares. Use it in the spirit of gnu. But we'd hope you credit us if
+you take pieces out of it :)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,80 @@
+/******************************o.
+
+Here are some settings you may want to fix :)
+VIDEO and AUDIO are set in the makefile.	 
+*/
+
+#define BUFW 320
+#define BUFH 200
+/*
+	The size (width&height) of the display buffer.
+	
+	320x200 is smooth on a 386.
+
+	Svgalib: the best-fitting 256 color mode will be searched
+	automatically.
+*/
+
+#define VGARETRACE 0 
+/* 
+	1 = Svgalib waits for the vertical retrace before dumping the
+       framebuffer.       
+*/
+
+#define ASMLOOPS 0
+/*
+	386 = use the i386-optimized asm loops (slightly buggy)
+	0   = pure c source (recommended for non-pc machines :)
+*/
+
+#define OUTFREQ 22050
+/*
+	Audio output frequency. 
+*/
+
+#define FRAGSIZE 10	/* size = 2^n, n=7..17 */
+#define NUMFRAGS 40	/* somewhere between 2..255, i think */
+/*
+	The number and size of the audio buffers.
+
+	If your machine has problems in keeping the mixbuffer filled, you
+	an try to increase these values. However those 10,40 are quite ok
+	for a 386dx/25 with an old soundblaster.
+	
+	Prefer increasing NUMFRAGS unless you want an action-halt-
+	action-halt style multimedia performance a la windows.
+
+	We still have problems in keeping the audio up in all
+	circumstances.. such as leaving the svgalib console or while
+	performing some window manager functions.		
+*/
+
+#define WINNAME "3x666"
+/*
+	The name for the x window.
+*/
+
+#define SLEEPY 0
+/* 
+	1 = sleep between frames if there's nothing to do
+	    originally implemented for a better cpu usage
+	    but i don't think it is of any relevant use here
+	    
+	0 = use dummyloop
+
+ */
+/*	All right! Now save the file and type make ("em ay kee ee")
+/ \
+
+.o*************/
+
+/* don't touch these: */
+
+#define DEMOHZ 100
+
+/* maybe these shouldn't be here */
+#define ROWTIX 6
+#define MAXROWLGT TIKLGT*ROWTIX
+
+#define vga 0
+#define X11 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/file_id.diz	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,6 @@
+ocsa presents : 3x666 : da linux demo.
+--.---.---.---:---.---^---.---.---.--'
+system: unix/linux, gcc, not many mips
+video : X11/vga, any*any*8bit__     __
+audio : devdsp/nosnd, mono8b  (______) 
+disk :::bin size abt 10..20k  (o .. o)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/oxl.c	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,298 @@
+/*** OCSALiB 0.0.1alpha -- see oxl.h ***/
+
+#include "config.h"
+
+#if VIDEO==vga
+	#include "vga.h"
+#endif
+#if VIDEO==X11
+	#include "X11/Xlib.h"
+	#include "X11/Xutil.h"
+#endif
+
+#if AUDIO
+	#include "sys/soundcard.h"
+	#include "sys/ioctl.h"
+#endif
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "fcntl.h"
+#include "unistd.h"
+#include "malloc.h"
+#include "time.h"
+#include "sys/time.h"
+
+#ifdef __linux__
+#include "linux/string.h"
+#else
+#include "string.h"
+#endif
+
+#define DEMOHZ 100
+
+int TIKLGT;
+
+typedef struct { int r,g,b; } rgb;
+
+/*** gLOBAL vARS ***/
+
+int AUFREQ=OUTFREQ;
+
+#if AUDIO==1
+	int devdsp;
+	char *audiobuf;
+#else
+	int baseclock;
+#endif
+
+#if VIDEO==vga
+	int SCRH,SCRW;
+#endif
+
+#if VIDEO==X11
+	Display *oxl_disp;
+	Visual *oxl_vis;
+	GC oxl_gc;
+	int oxl_win,oxl_scr;
+	Colormap oxl_pal;
+	XImage *oxl_im;
+	XColor oxl_col[256];
+#endif
+
+void oxl_init_video()
+{
+	printf("oxl: buffer size = %ix%ix8bit\n",BUFW,BUFH);
+
+#if VIDEO==vga
+{	int i,fit=0,fitw=9999,fith=9999;
+	vga_modeinfo*inf;
+	
+	if(vga_init()){printf("oxl: can't init svgalib!\n");exit(0);}
+
+	/* Finds the best-fitting 256-color videomode */
+	for(i=0;i<GLASTMODE;i++){
+		if(vga_hasmode(i)){
+			inf=vga_getmodeinfo(i);
+		   if((inf->colors==256)&&
+			   (inf->width >=BUFW)&&(inf->height>=BUFH)&&
+			   (inf->width <=fitw)&&(inf->height<=fith)){
+			 	fith=SCRH=inf->height;
+				fitw=SCRW=inf->width;
+				fit=i;
+	}	}	}
+
+	if(!fit){
+		printf("oxl: no suitable modes found.\n");exit(0);}
+	else{
+		printf("oxl: using %s\n",vga_getmodename(fit));
+		vga_setmode(fit);
+	}
+}
+#endif	
+
+#if VIDEO==X11
+{	XSetWindowAttributes att;
+	Window rtwin;
+
+	/* get some pointers'n'stuff */
+	if(!(oxl_disp=XOpenDisplay(NULL))){
+		perror("oxl: can't open X display!\n");exit(0);}
+	oxl_scr=DefaultScreen(oxl_disp);
+	oxl_gc=DefaultGC(oxl_disp,oxl_scr);
+	oxl_vis=DefaultVisual(oxl_disp,oxl_scr);
+	
+	rtwin=DefaultRootWindow(oxl_disp);
+
+	/* don't store the contents */
+	att.backing_store=NotUseful;
+
+	/* allocate a private colormap */
+	oxl_pal=XCreateColormap(oxl_disp,rtwin,oxl_vis,AllocAll);
+	att.colormap=oxl_pal;
+
+	/* a black emptiness replaces the cursor */
+	{XColor blk;Pixmap e;
+	blk.red=blk.green=blk.blue=0;
+	blk.flags=DoRed+DoGreen+DoBlue;
+	e=XCreatePixmap(oxl_disp,rtwin,2,2,1);	
+	att.cursor=XCreatePixmapCursor(oxl_disp,e,e,&blk,&blk,0,0);}
+
+	oxl_win=XCreateWindow(
+		oxl_disp,rtwin,
+		0,0,BUFW,BUFH,4,
+		8,	/* colordepth */
+		InputOutput,
+		oxl_vis,
+		CWBackingStore+CWColormap+CWCursor,&att);
+
+	/* tell the wm you can't resize it */
+	{XSizeHints shints;
+	shints.min_width= shints.max_width= BUFW;
+	shints.min_height=shints.max_height=BUFH;
+	shints.flags=PMinSize+PMaxSize;
+	
+	/* set the names etc */
+	XSetStandardProperties(
+		oxl_disp,oxl_win,
+		WINNAME,WINNAME,
+		None,NULL,0,
+		&shints);
+	}
+
+	/* and draw the window */
+	XMapWindow(oxl_disp,oxl_win);
+	XSync(oxl_disp,False);
+
+	/* create the ximage to be hooked on the frame buffer */
+	oxl_im=XCreateImage(oxl_disp,oxl_vis,
+		8,ZPixmap,  /* depth, format */
+		0,NULL,     /* offset, data */
+		BUFW,BUFH,  /* width, height */
+		32,BUFW);   /* align bits, bytes per scanline */
+	oxl_im->bitmap_unit=32;		
+	
+	/* some values for the palette */
+	{int i;
+	for(i=0;i<256;i++){
+		oxl_col[i].flags=DoRed|DoGreen|DoBlue;
+		oxl_col[i].pixel=i;
+		oxl_col[i].pad=0;
+	}}
+}
+#endif
+}
+
+void oxl_init_audio(int rowtix)
+{
+#if AUDIO==1
+	int tmp;
+	printf("oxl: initing oss..\n");
+
+	devdsp=open("/dev/dsp",O_WRONLY|O_NDELAY,0);
+	ioctl(devdsp,SNDCTL_DSP_SPEED,&AUFREQ);
+	
+	tmp=(NUMFRAGS<<16)|FRAGSIZE;
+	ioctl(devdsp,SNDCTL_DSP_SETFRAGMENT,&tmp);
+	ioctl(devdsp,SNDCTL_DSP_SYNC,0);
+	
+	tmp=0;ioctl(devdsp,SNDCTL_DSP_STEREO,&tmp);	/* mono */	
+	tmp=8;ioctl(devdsp,SNDCTL_DSP_SAMPLESIZE,&tmp);	/* 8*/
+
+	audiobuf=malloc((rowtix*AUFREQ/DEMOHZ)*sizeof(char));
+#endif
+}
+
+#if AUDIO==0
+int klok()	/* just an internal clumsie */
+{
+	struct timeval tym;
+	gettimeofday(&tym,NULL);
+	return (tym.tv_sec*DEMOHZ)+(tym.tv_usec*DEMOHZ/1000000);
+}
+#endif
+
+void oxl_init_timer()
+{
+#if AUDIO==0
+	baseclock=klok();
+#endif
+}
+
+void oxl_end()
+{
+/* These things should be done automatically on exit but
+   let's put them here anyway :) */
+
+#if AUDIO==1
+	close(devdsp);
+#endif
+
+#if VIDEO==vga
+	vga_setmode(TEXT);
+#endif
+
+#if VIDEO==X11
+	XCloseDisplay(oxl_disp);
+#endif
+}
+
+int oxl_timer()
+{
+#if AUDIO==1
+	count_info p;
+	ioctl(devdsp,SNDCTL_DSP_GETOPTR,&p);
+	return p.bytes/TIKLGT;
+#else
+	return (klok()-baseclock);
+#endif
+}
+
+void oxl_doaudio(int*(*player)(void))
+{
+#if AUDIO==1
+	audio_buf_info a;
+	
+	for(;;){
+	ioctl(devdsp,SNDCTL_DSP_GETOSPACE,&a);
+	if(a.fragments<a.fragstotal/2) break;
+
+	{register int i,*s=(*player)(); /* output 8bit	*/
+	int lgt=*s++;char*d=audiobuf;
+	for(i=lgt;i;i--){
+		int x=*s++>>8;
+		if(x<0)x=0;else if(x>255)x=255;
+		*d++=x;
+		}
+	write(devdsp,audiobuf,lgt);
+	}	
+	}
+#endif
+}
+
+void oxl_setpalette(rgb*pal)
+{
+#if VIDEO==vga
+	int *p=(int*)pal,*c;int pp[256*3],i;c=pp;
+	for(i=256*3;i;i--)*c++=*p++>>2;
+	vga_setpalvec(0,256,pp);
+#endif 
+
+#if VIDEO==X11
+{	int i;
+	rgb*p=pal;XColor *c=oxl_col;
+	for(i=256;i;i--){
+		c->red=(p->r<<8);
+		c->green=(p->g<<8);
+		c->blue=(p->b<<8);
+		c++;p++;
+	}
+	XStoreColors(oxl_disp,oxl_pal,oxl_col,256);
+}
+#endif
+}
+
+void oxl_doframe(char *vscr)
+{
+#if VIDEO==vga
+	int y0=(SCRH-BUFH)>>1;
+	
+	#if VGARETRACE==1
+	vga_waitretrace();
+	#endif
+
+	if(SCRW==BUFW)
+ 	  vga_drawscansegment(vscr,0,y0,BUFW*BUFH);
+	else
+	{
+	 int y;char *s=vscr;int x0=(SCRW-BUFW)>>1;
+	 for(y=y0;y<y0+BUFH;y++){vga_drawscansegment(s,x0,y,BUFW);s+=BUFW;}
+	}
+#endif
+
+#if VIDEO==X11 
+	oxl_im->data=vscr;
+	XPutImage(oxl_disp,oxl_win,oxl_gc,oxl_im,-1,-1,0,0,BUFW,BUFH);
+	XSync(oxl_disp,False);
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/oxl.h	Fri Mar 15 05:00:01 2013 +0200
@@ -0,0 +1,127 @@
+/******************** 
+
+	OCSALiB, the revolutionary -- version 0.0.1alpha
+	
+	(c) viznut/ocsa '98  vheikkil@hytti.uku.fi
+	
+	use it the way you like, i don't care :)
+	
+***************/
+
+typedef struct {int r,g,b; } rgb;
+
+extern void oxl_setpalette(rgb *pal); 
+extern void oxl_doframe(char *vscr);
+extern int oxl_timer(void);
+extern void oxl_doaudio(int*(player()));
+extern void oxl_init_video(void);
+extern void oxl_init_audio(int rowtix);
+extern void oxl_init_timer(void);
+extern void oxl_end(void);
+
+extern int AUFREQ, TIKLGT;
+
+/*x.
+
+	Just in case you _may_ want to use this in your own proggie (urgh)
+	let's put some documentation here :)
+
+** FUNCTIONS **
+
+void oxl_setpalette(rgb *pal)
+
+	pal is a table containing three ints (r,g,b) for every color.
+	the values vary 0..255. 
+
+void oxl_doframe(char *vscr)
+
+	blits the contents of the offscreen buffer to the screen.
+	the size of the buffer is BUFW * BUFH * 8 bits.
+
+int oxl_timer(void)
+
+	the current timer value. the number of timer ticks per second is
+	defined by the DEMOHZ constant.
+
+void oxl_doaudio(int*(player()));
+
+	fills the audio output buffers up to 50%.
+	
+	player is a user-specified function returning a pointer to some raw
+   audio data (e.g. the mixer output for the next row of a pattern)
+
+	the first int of the data is the length of the rest (in ints).
+
+	the buffer is int* but the data is 16bit unsigned. values going out
+   of the range 0..65535 will be clipped.
+
+	AUFREQ specifies the output frequency.
+
+void oxl_init_video(void);
+
+   adjusts the display for the demo. 	
+	oxl_doframe and oxl_setpalette need this.	
+
+void oxl_init_audio(int rowtix);
+ 	
+	inits the audio stuff, possibly changing the value of AUFREQ. 
+   rowtix is the maximum length (in ticks) of an audio chunk produced
+   by int*(player()). (the 'physical length' in samples is therefore
+   rowtix*AUFREQ/DEMOHZ)
+
+   oxl_doaudio needs this.  does nothing if nosound.
+
+void oxl_init_timer(void);
+
+	starts the timer. oxl_timer needs this.
+	
+	with sounds on, the timing is actually based on the byte counter of
+   the sound device but put this in your code anyway.
+
+void oxl_end(void);
+
+	closes the multimedia subsystems. these things should be done
+   automatically when the program terminates, so you really don't need
+   this function.
+
+** CONSTANTS REQUIRED **
+
+	AUDIO (0/1)
+	VIDEO (vga/X11)
+	BUFW, BUFH (buffer size)
+	DEMOHZ (timer ticks per second)
+
+** THINGS TO DO **
+
+	- A guard process that tries to keep up the audio even if the main
+     loop is frozen. (e.g. if the svgalib screen is not active or if
+     you move the window in X)
+
+	- Make sure the window start address is properly aligned for the
+     maximum performance.
+
+	- Do not calculate the contents of the buffer if the screen/window
+     is not visible.
+
+	- A variable palette size: if the palette fits in the end of the
+     default colormap, we have to be able to use it instead of rudely
+     using a private map.
+   
+   - Support for visual depths other than 8bpp.
+
+	- Support for 16-bit multimedia sound systems. Stereo?
+
+	- mSDoS support (for dummies)
+
+	- AAlib support
+
+	- An automatical reselection of X11 gfx mode to best fit the size of
+     the buffer.
+     
+   - X fullscreen mode
+   
+   - X rootwindow mode
+
+	- Etc etc... but still trying to keep it in a relevant size ;)
+
+.x*/