diff -urN phorus-0.9alpha6.orig/include/phorus.h phorus-0.9alpha6/include/phorus.h
--- phorus-0.9alpha6.orig/include/phorus.h	Sat Dec  5 22:02:19 1998
+++ phorus-0.9alpha6/include/phorus.h	Sun Dec  6 17:50:44 1998
@@ -7,12 +7,17 @@
 #ifndef _PHORUS_H
 #define _PHORUS_H
 
+#define USE_GGI
+
 // Configs and such..
-#ifdef __linux__
+#ifdef __unix
 // #define NDEBUG
-#define HAVE_X11
-// #define HAVE_GGI
-#define HAVE_SVGA
+#ifdef USE_GGI
+#define HAVE_GGI
+#else
+// #define HAVE_X11
+// #define HAVE_SVGA
+#endif
 
 // ESD support is broken at the moment. Don't use.
 // If you want to try to fix it, you're welcome to, but I won't support it
@@ -289,10 +294,14 @@
 extern int			m_res_musvol;
 
 // Outside interfaces.. woo.
-#ifdef __linux__
-extern struct Interface_t	int_X11,int_GGI,int_SVGA;
+#ifdef USE_GGI
+extern struct Interface_t	int_GGI;
+#else
+#ifdef __unix
+extern struct Interface_t	int_X11,int_SVGA;
 #else
 extern struct Interface_t	int_DirectX;
+#endif
 #endif
 
 /*********************************************** Prototypes		*/
diff -urN phorus-0.9alpha6.orig/src/Makefile phorus-0.9alpha6/src/Makefile
--- phorus-0.9alpha6.orig/src/Makefile	Sat Dec  5 22:42:13 1998
+++ phorus-0.9alpha6/src/Makefile	Sun Dec  6 21:24:05 1998
@@ -21,10 +21,10 @@
 	d_draw.o d_image.o d_pcx.o d_trans.o g_ai.o g_init.o g_map.o \
 	g_render.o g_run.o e_main.o
 INCLUDES=-I../include
-LIBS=-L../lib -linterface -L/usr/X11R6/lib -lX11 -lXext -lvga
+LIBS=-L../lib -linterface -lm -L/misc/hacks/vol/ggi/lib -lggi
 
 #CFLAGS=-Wall -march=pentium -O3 -DNDEBUG
-CFLAGS=-Wall -march=pentium -O3 -g
+CFLAGS=-Wall -O3 -g
 LDFLAGS=
 
 PROGNAME=$(BINDIR)/$(BINNAME)
diff -urN phorus-0.9alpha6.orig/src/linux/Makefile phorus-0.9alpha6/src/linux/Makefile
--- phorus-0.9alpha6.orig/src/linux/Makefile	Sat Dec  5 22:42:05 1998
+++ phorus-0.9alpha6/src/linux/Makefile	Sun Dec  6 21:25:19 1998
@@ -14,12 +14,11 @@
 CC=gcc
 
 #DIRECTORIES=draw misc game
-OFILES= i_linux.o i_net.o i_svga.o i_x11.o
-INCLUDES=-I../../include
-LIBS=-L/usr/X11R6/lib -lX11 -lXext -lvga -lm
+OFILES= i_linux.o i_sound.o i_net.o i_ggi.o
+INCLUDES=-I../../include -I/misc/hacks/vol/ggi/include
+LIBS = -L/misc/hacks/vol/ggi/lib -lggi
 
-#CFLAGS=-Wall -march=pentium -O3 -DNDEBUG
-CFLAGS=-Wall -march=pentium -O3 -g
+CFLAGS=-Wall -O3 -g
 LDFLAGS=
 
 LIBFILE=$(LIBDIR)/$(LIBNAME)
diff -urN phorus-0.9alpha6.orig/src/linux/i_ggi.c phorus-0.9alpha6/src/linux/i_ggi.c
--- phorus-0.9alpha6.orig/src/linux/i_ggi.c	Thu Jan  1 01:00:00 1970
+++ phorus-0.9alpha6/src/linux/i_ggi.c	Sun Dec  6 21:22:56 1998
@@ -0,0 +1,327 @@
+// Phorus
+//
+// i_ggi.c
+//
+// LibGGI handling and other goodies.
+
+#include "phorus.h"
+#ifdef HAVE_GGI
+#include "graphics.h"
+#include "keyboard.h"
+#include <ggi/ggi.h>
+#include <ctype.h>
+#include <signal.h>
+
+struct iGGI_data {
+	ggi_visual_t	         vis;
+	const ggi_directbuffer  *dbuf;
+	int		         x, y;
+	// Color stuff.
+	int			pseudo,grayscale;
+	int			bitsh_r,bitsh_g,bitsh_b;
+	int			sh_r,sh_g,sh_b;
+};
+
+int i_ggi_detect(void) {
+	return 1;
+}
+
+static void i_ggi_sigpipe_handler() {
+	i_dprintf(("SIGPIPE received.\n"));
+}
+
+static void i_ggi_sigsegv_handler() {
+	i_error(("SIGSEGV received. Terminating.\n"));
+	ggiExit();
+	exit(1);
+}
+
+struct Screen_t *i_ggi_init(int xsize, int ysize, int bpp) {
+	ggi_mode	  mode;
+	int		  tbpp;
+	struct Screen_t  *cow=NULL;
+	struct iGGI_data *moo=NULL;
+	
+	if (screen) return screen;
+
+	if (ggiInit() < 0) {
+		i_error(("Unable to init LibGGI!\n"));
+		return NULL;
+	}
+
+	moo=calloc(1,sizeof(struct iGGI_data));
+	if (!(moo->vis = ggiOpen(NULL))) {
+		i_error(("Unable to open default visual.\n"));
+		free(moo);
+		ggiExit();
+		return NULL;
+	}
+	ggiSetFlags(moo->vis, GGIFLAG_ASYNC);
+	
+	if (ggiSetGraphMode(moo->vis, xsize, ysize, GGI_AUTO, GGI_AUTO,
+			    GT_AUTO) != 0) {
+		i_error(("Unable to set default mode!\n"));
+		ggiClose(moo->vis);
+		ggiExit();
+		return NULL;
+	}
+	ggiGetMode(moo->vis, &mode);
+
+	tbpp = GT_SIZE(mode.graphtype);
+
+	i_dprintf(("LibGGI is at %d BPP.\n", tbpp));
+	
+	moo->pseudo = (GT_SCHEME(mode.graphtype) == GT_PALETTE)
+		||    (GT_SCHEME(mode.graphtype) == GT_GREYSCALE);
+	moo->grayscale = (GT_SCHEME(mode.graphtype) == GT_GREYSCALE);
+	cow=calloc(1,sizeof(struct Screen_t));
+	cow->image.bpp = tbpp;
+	moo->x = cow->image.xs = cow->image.rxs = xsize;
+	moo->y = cow->image.ys = cow->image.rys = ysize;
+	cow->image.gran = 30;
+	cow->image.flags = ImFlag_Flat;
+
+	if (!moo->pseudo) {
+#if 0
+		cow->rgb_mask=((8-moo->sh_r)*100)+
+			((8-moo->sh_g)*10)+
+			(8-moo->sh_b);
+#endif
+	}
+	
+	if ((moo->dbuf = ggiDBGetBuffer(moo->vis, 0)) != NULL
+	    && (moo->dbuf->type & GGI_DB_SIMPLE_PLB)
+	    && moo->dbuf->buffer.plb.stride == xsize*((tbpp+7)/8)) {
+		cow->image.data = moo->dbuf->write;
+		i_dprintf(("Using DirectBuffer.\n"));
+	} else {
+		moo->dbuf = NULL;
+		cow->image.data = malloc(xsize*ysize*((bpp+7)/8));
+	}
+	cow->image.bpp = GT_SIZE(mode.graphtype);
+
+#if 0
+	// And now.. let's set the 1x1 pixel cursor.
+	if (!m_findarg("-defcursor")) {
+		const char		cursor_data[8]={0x01,0,0,0,0,0,0,0};
+		XColor			xc_a,xc_b;
+		Pixmap			cursor_pixmap;
+		int			cursor;
+		memset(&xc_a,0,sizeof(xc_a));
+		memset(&xc_b,0,sizeof(xc_b));
+		cursor_pixmap=XCreateBitmapFromData(moo->display,moo->window,
+				cursor_data,8,8);
+		cursor=XCreatePixmapCursor(moo->display,cursor_pixmap,cursor_pixmap,
+				&xc_a,&xc_b,0,0);
+		XDefineCursor(moo->display,moo->window,cursor);
+	}
+#endif
+	
+	screen=cow;
+	cow->is=moo;
+	return screen;
+}
+
+void i_ggi_done(int dtype) {
+	iface=NULL;
+	if (screen) {
+		struct iGGI_data *moo=screen->is;
+		if (moo) {
+			if (moo->dbuf != NULL) {
+				free(screen->image.data);
+			}
+			ggiClose(moo->vis);
+			ggiExit();
+		}
+		free(screen->is);
+		free(screen);
+		i_dprintf(("Clean interface shutdown.\n"));
+	}
+	return;
+}
+
+// ----------------------------------------------------- Palette Handling
+
+static int gammastate=1;
+
+int i_ggi_getrgbcolor(int r, int g, int b) {
+#define BITSHIFT	8
+	struct iGGI_data *is;
+	ggi_color col;
+	if (!screen||!screen->is) return -1;
+	is=screen->is;
+	if (is->grayscale) {
+		i_dprintf(("Grayscale?!?\n"));
+	} else if (!is->pseudo) {
+		if (gammastate&&
+			(r!=d_image_transcolors[0]||
+			 g!=d_image_transcolors[1]||
+			 b!=d_image_transcolors[2]))
+			{ r+=m_res_gamma; g+=m_res_gamma; b+=m_res_gamma; }
+		if (r>0xff) r=0xff; if (g>0xff) g=0xff; if (b>0xff) b=0xff;
+		if (r<0) r=0; if (g<0) g=0; if (b<0) b=0;
+	}
+	col.r = r << BITSHIFT;
+	col.g = g << BITSHIFT;
+	col.b = b << BITSHIFT;
+	return ggiMapColor(is->vis, &col);
+}
+
+void i_ggi_mappal(unsigned char *pal) {
+	struct iGGI_data *moo;
+	ggi_color colors[256];
+	int i;
+	
+	if (!screen||!(moo=screen->is)) return;
+
+	for (i=0;i<256;i++) {
+		int r,g,b;
+		r=(*pal++ +m_res_gamma);
+		g=(*pal++ +m_res_gamma);
+		b=(*pal++ +m_res_gamma);
+		
+		if (r<0) r=0;
+		if (r>255) r=255;
+		if (g<0) g=0;
+		if (g>255) g=255;
+		if (b<0) b=0;
+		if (b>255) b=255;
+		
+		colors[i].r=r<<8;
+		colors[i].g=g<<8;
+		colors[i].b=b<<8;
+	}
+	ggiSetPalette(moo->vis, 0, 256, colors);
+}
+
+void i_ggi_setgammastate(int gam) {
+	gammastate=gam;
+}
+
+// ----------------------------------------------------- Keyboard input
+static void keyboard_handle(uint32 key, int press) {
+	struct iGGI_data *moo;
+	int nkey;
+	if (!screen||!screen->is) return;
+	moo=screen->is;
+	// convert key to game key.. Insert other keys as needed..
+	switch (key) {
+	case GIIK_Left: case GIIK_P4:
+			nkey=Key_LeftArrow;	break;
+	case GIIK_Right: case GIIK_P6:
+			nkey=Key_RightArrow;	break;
+	case GIIK_Up: case GIIK_P8:
+			nkey=Key_UpArrow;	break;
+	case GIIK_Down: case GIIK_P2:
+			nkey=Key_DownArrow;	break;
+	case GIIUC_Escape:	nkey=Key_Escape;	break;
+	case GIIK_PageUp: case GIIK_P9:
+			nkey=Key_PgUp;		break;
+	case GIIK_PageDown: case GIIK_P3:
+			nkey=Key_PgDn;		break;
+	case GIIK_Home: case GIIK_P7:
+			nkey=Key_Home;		break;
+	case GIIK_End: case GIIK_P1:
+			nkey=Key_End;		break;
+	case GIIUC_Return: nkey=Key_Enter;		break;
+	case GIIUC_Tab:	nkey=Key_Tab;		break;
+	case ' ':	nkey=Key_Space;		break;
+	case GIIK_F1:	nkey=Key_F1;		break;
+	case GIIK_F2:	nkey=Key_F2;		break;
+	case GIIK_F3:	nkey=Key_F3;		break;
+	case GIIK_F4:	nkey=Key_F4;		break;
+	case GIIK_F5:	nkey=Key_F5;		break;
+	case GIIK_F6:	nkey=Key_F6;		break;
+	case GIIK_F7:	nkey=Key_F7;		break;
+	case GIIK_F8:	nkey=Key_F8;		break;
+	case GIIK_F9:	nkey=Key_F9;		break;
+	case GIIK_F10:	nkey=Key_F10;		break;
+	case GIIK_F11:	nkey=Key_F11;		break;
+	case GIIK_F12:	nkey=Key_F12;		break;
+	case GIIK_Pause:	nkey=Key_Pause;		break;
+	case GIIK_ShiftL: case GIIK_ShiftR:
+			nkey=Key_Shift;		break;
+	case GIIK_CtrlL: case GIIK_CtrlR:
+			nkey=Key_Ctrl;		break;
+	case GIIK_AltL: case GIIK_AltR: case GIIK_MetaL: case GIIK_MetaR:
+		nkey=Key_Alt;		break;
+	default:
+		nkey=tolower(key);
+		break;
+	}
+	if (nkey>=NoKey||nkey<0) return;
+	if (i_key_status[nkey].active==press) return;
+	// add to queue
+	if (i_add_key_to_queue&&i_key_status[nkey].active!=press) {
+		struct Keyboard_Queue_t cow;
+		cow.key=nkey;
+		cow.active=press;
+		cow.tic=i_tics;
+		if (i_nkeys_in_queue<MAX_KEYS)
+			memcpy(&i_kbd_queue[i_nkeys_in_queue++],&cow,
+			       sizeof(struct Keyboard_Queue_t));
+		else {
+			i_error(("i_nkeys_in_queue >= MAX_KEYS !!! VERY BAD!\n"));
+		}
+	}
+	i_key_status[nkey].active=press;
+	if (press) {
+		i_key_status[nkey].tic=i_tics;
+		i_key_status[nkey].repeats=0;
+	}
+}
+
+// ----------------------------------------------------- Miscellaneous
+int i_ggi_update(int drawframe) {
+	struct iGGI_data *moo;
+	static int tics=0;
+	ggi_event ggiev;
+	int can_render;
+	struct timeval tv = {0, 0};
+
+	if (!screen||!screen->is) return 0;
+	moo=(struct iGGI_data *)screen->is;
+	i_timer_update();
+	// printf("(%d, %d)\n",i_tics,tics);
+	// if (i_tics<tics||(i_tics>(tics+1)))
+		can_render=1;
+	// else	can_render=0;
+	// Handle input and stuff
+	while (ggiEventPoll(moo->vis, emKey, &tv) & emKey) {
+		ggiEventRead(moo->vis, &ggiev, emKey);
+		switch(ggiev.any.type) {
+		case evKeyPress:
+			keyboard_handle(ggiev.key.label,TRUE);
+			break;
+		case evKeyRelease:
+			keyboard_handle(ggiev.key.label,FALSE);
+			break;
+		}
+		tv.tv_sec = tv.tv_usec = 0;
+	}
+	if (drawframe&&can_render) {
+		tics=i_tics;
+		if (moo->dbuf == NULL) {
+			ggiPutBox(moo->vis, 0, 0, moo->x, moo->y,
+				  screen->image.data);
+		}
+		ggiFlush(moo->vis);
+	}
+	return can_render;
+}
+
+// ----------------------------------------------------- Interface Struct
+
+struct Interface_t int_GGI={
+	i_ggi_detect,
+	i_ggi_init,
+	NULL,
+	NULL,
+	i_ggi_update,
+	i_ggi_done,
+	i_ggi_getrgbcolor,
+	i_ggi_mappal,
+	i_ggi_setgammastate,
+};
+
+#endif
diff -urN phorus-0.9alpha6.orig/src/linux/i_linux.c phorus-0.9alpha6/src/linux/i_linux.c
--- phorus-0.9alpha6.orig/src/linux/i_linux.c	Sat Dec  5 22:02:26 1998
+++ phorus-0.9alpha6/src/linux/i_linux.c	Sun Dec  6 21:28:40 1998
@@ -2,24 +2,13 @@
 //
 // i_linux.c
 //
-// Linux specifics.
+// Unix specifics.
 
-#ifdef __linux__
 #include "phorus.h"
 #include "keyboard.h"
-#include "sound.h"
 
 #include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/soundcard.h>
 #include <errno.h>
-#include <signal.h>
-
-#ifdef HAVE_ESD
-#include <dlfcn.h>
-#include <esd.h>
-#endif
 
 // Add more as needed..
 static struct Interface_t *intrfaces[]={
@@ -73,7 +62,7 @@
 }
 
 int i_pf_actual(char *format, ...) {
-	va_list *arg;
+	va_list arg;
 	int i;
 	va_start(arg,format);
 	i=vprintf(format,arg);
@@ -219,316 +208,3 @@
 	i_tics=0;
 	gettimeofday(&time_start,NULL);
 }
-
-// Happyfun sound code.
-
-static const int bitrates[4]={0,44100,88200,176400};
-static const int bufsizes[4]={512,1024,2048,4096};
-static const int passto[4]={10,11,12,13};
-
-static int sound_fd=-1;
-static int sound_rate=-1;
-static int sound_bits=-1;
-static int sound_stereo=0;
-static int sound_bufsize=0;
-
-static char *sound_blankbuf=NULL;
-
-static struct Sound_t **sounds;
-static int nsounds;
-
-static struct SoundPlaying_t **sounds_playing;
-static int nsounds_playing;
-
-static int sound_id=1;
-
-void i_sound_close(void) {
-	struct itimerval itime;
-
-	if (sound_fd<0) return;
-	// Kill off the timer.
-	itime.it_interval.tv_sec=0;
-	itime.it_interval.tv_usec=0;
-	itime.it_value.tv_sec=0;
-	itime.it_value.tv_usec=0;
-	if (setitimer(ITIMER_REAL,&itime,NULL)<0)
-		i_error(("setitimer failed with error: %s\n",strerror(errno)));
-
-	// Close the descriptor
-	close(sound_fd);
-	sound_fd=-1;
-}
-
-int i_sound_init(int rate, int bits, int stereo) {
-	struct sigaction sa;
-	struct itimerval itime;
-	int temp;
-	int bufdata=2;
-	int bitrate;
-	if (sound_fd>=0) i_sound_close();
-
-#ifdef HAVE_ESD
-	if (m_findarg("-esd")) do {
-		void *libesd;
-		int (*esd_playstream)(esd_format_t f, int r, char *h, char *n);
-		char *err;
-		int fmt;
-		// Whee.. ESD support it is, although it's a slowass piece
-		// of crap at anything but 44KHz/16bit/stereo
-		
-		// This won't work. I need some way of checking to see if
-		// there's anything in the buffer so I can have a nice, steady
-		// buffer flow that happens in /real time/.
-		
-		if (!(libesd=dlopen("libesd.so",RTLD_LAZY))) {
-			i_error(("Can't open libesd(%s). Falling back to regular sound.\n",
-				dlerror()));
-			break;
-		}
-		
-		esd_playstream=dlsym(libesd,"esd_play_stream");
-		if ((err=dlerror())) {
-			i_error(("Couldn't get esd_play_stream(%s), falling back to regular sound.\n",
-				err));
-			dlclose(libesd);
-			break;
-		}
-		fmt=((bits==8)?ESD_BITS8:0)|((stereo==0)?ESD_MONO:0)|ESD_STREAM|ESD_PLAY;
-		sound_fd=esd_playstream(fmt,rate,"","Phorus");
-		if (sound_fd<=0) {
-			sound_fd=-1;
-			i_error(("esd_play_stream failed. Falling back.\n"));
-			dlclose(libesd);
-			break;
-		}
-		// don't need libesd anymore...
-		dlclose(libesd);
-		i_printf(("Using ESD.\n"));
-	} while(0);
-#endif
-
-	if (sound_fd<0) {
-		if ((sound_fd=open("/dev/dsp",O_WRONLY,0))<0) {
-			i_printf(("i_sound_init: Couldn't open sound card. Disabling sound.\n"));
-			return 0;
-		}
-
-		if (fcntl(sound_fd,F_SETFL,O_NONBLOCK)<0) {
-			i_printf(("i_sound_init: Couldn't set nonblocking IO. Disabling sound.\n"));
-			i_sound_close();
-			return 0;
-		}
-	
-		if (ioctl(sound_fd,SNDCTL_DSP_SAMPLESIZE,&bits)<0) {
-			i_printf(("i_sound_init: Can't set sample size of %d. Disabling sound.\n"));
-			i_sound_close();
-			return 0;
-		}
-		if (stereo>0) stereo=1; else stereo=0;
-		if (ioctl(sound_fd,SNDCTL_DSP_STEREO,&stereo)<0) {
-			i_printf(("i_sound_init: Can't set mono/stereo. Disabling sound.\n"));
-			i_sound_close();
-			return 0;
-		}
-		if (ioctl(sound_fd,SNDCTL_DSP_SPEED,&rate)<0) {
-			i_printf(("i_sound_init: Can't set sound rate. Disabling sound.\n"));
-			i_sound_close();
-			return 0;
-		}
-		
-		bitrate=rate*(bits>>3)*(stereo+1);
-		
-		for (temp=0;temp<3;temp++)
-			if (bitrate>=bitrates[temp]&&bitrate<bitrates[temp+1])
-				break;
-		bufdata=temp;
-		
-		temp=passto[bufdata]|(3<<16);
-		if (ioctl(sound_fd,SNDCTL_DSP_SETFRAGMENT,&temp)<0) {
-			i_printf(("i_sound_init: Can't set fragment size of 1024. Disabling sound.\n"));
-			i_sound_close();
-			return 0;
-		}
-	}
-	
-	// Alright, now set the i_sound_update() timer.
-	// Also, fry the current abort(), whatever it may be. I'm not using
-	// it for anything anyway.
-	sa.sa_handler=(void *)i_sound_update;
-#ifdef SA_RESTART
-	sa.sa_flags=SA_RESTART;
-#else
-	sa.sa_flags=0;
-#endif
-	sigemptyset(&sa.sa_mask);
-	sigaction(SIGALRM,&sa,NULL);
-	
-	itime.it_interval.tv_sec=0;
-	itime.it_interval.tv_usec=10000;
-	itime.it_value.tv_sec=0;
-	itime.it_value.tv_usec=10000;
-	if (setitimer(ITIMER_REAL,&itime,NULL)<0)
-		i_error(("setitimer failed with error: %s\n",strerror(errno)));
-	
-	// No problems. *boggle*.
-	sound_rate=rate;
-	sound_bits=bits;
-	sound_stereo=stereo;
-
-	s_sound_mixat(rate,bits,stereo);
-	
-	sound_bufsize=bufsizes[bufdata];
-	
-	i_printf(("Sound enabled. Rate: %d  Bits: %d  %s  Bufsize: %d\n",
-		sound_rate,sound_bits,sound_stereo?"Stereo":"Mono",
-		sound_bufsize));
-	
-	if (sound_blankbuf) free(sound_blankbuf);
-	sound_blankbuf=malloc(sound_bufsize);
-	if (bits==8)
-		memset(sound_blankbuf,128,sound_bufsize);
-	else if (bits==16)
-		memset(sound_blankbuf,0,sound_bufsize);
-	return 1;
-}
-
-void i_sound_update(void) {
-	audio_buf_info ainfo;
-	int i,anysound=0;
-	char buf[8192];
-	if (sound_fd<0) return;
-	// Make sure there's enough room for our block.
-
-	if (ioctl(sound_fd,SNDCTL_DSP_GETOSPACE,&ainfo)<0||
-		ainfo.bytes<sound_bufsize)
-		return;
-	
-	// Well, we know there's a buffer update, so let the music stuff
-	// do it's thing.
-	s_mod_update(sound_bufsize);
-
-	for (i=0;i<nsounds_playing;i++) if (sounds_playing[i]) {
-		if (!anysound)
-			memset(buf,0,sound_bufsize*2);
-		anysound++;
-		// Mix to buffer..
-		s_sound_mix(buf,sound_bufsize,sounds_playing[i]);
-	}
-	
-	// Let's just call this one block for now.
-	if (anysound) {
-		// Final bounds check and tossage of everything
-		s_sound_finalmix(buf,sound_bufsize);
-		if (write(sound_fd,buf,sound_bufsize)!=sound_bufsize) {
-			i_error(("i_sound_init: Error writing to sound! Closing sound..\n"));
-			i_sound_close();
-			return;
-		}
-	} else {
-		if (write(sound_fd,sound_blankbuf,sound_bufsize)!=sound_bufsize) {
-			i_error(("i_sound_init: Error writing to sound! Closing sound..\n"));
-			i_sound_close();
-			return;
-		}
-	}
-}
-
-int i_sound_play(int soundnum, int vol, int pan, float delta, int flags) {
-	struct SoundPlaying_t *cow;
-	int i;
-	if (sound_fd<0||vol<=0||delta<=0.0) return -1;
-	for (i=0;i<nsounds;i++) if (sounds[i]&&sounds[i]->id==soundnum)
-		break;
-	if (i==nsounds) return -1;
-	if (vol>255) vol=255;
-	if (pan<-128) pan=-128;
-	if (pan>127) pan=127;
-	
-	cow=calloc(1,sizeof(struct SoundPlaying_t));
-	cow->sound=sounds[i];
-	cow->point=0;
-	cow->volume=vol;
-	cow->pan=pan;
-	cow->delta=(int)((float)sounds[i]->delta*delta);
-	cow->flags=flags|sounds[i]->flags;
-	cow->len=sounds[i]->len;
-	cow->id=sound_id++;
-	dpl_LINK(nsounds_playing,sounds_playing,cow,4,i);
-	return cow->id;
-}
-
-void i_sound_stop(int id) {
-	int i;
-	
-	if (id<=0) return;
-	
-	for (i=0;i<nsounds_playing;i++)
-		if (sounds_playing[i]&&sounds_playing[i]->id==id) {
-			free(sounds_playing[i]);
-			sounds_playing[i]=NULL;
-			return;
-		}
-}
-
-struct SoundPlaying_t *i_sound_playing_get(int id) {
-	int i;
-	if (id<=0) return NULL;
-	for (i=0;i<nsounds_playing;i++)
-		if (sounds_playing[i]&&sounds_playing[i]->id==id)
-			return sounds_playing[i];
-	return NULL;
-}
-
-int i_sound_register_file(char *filename) {
-	struct Sound_t *moo;
-	int i;
-	if (sound_fd<0) return -1;
-	// First check loaded sounds to see if this one's been loaded already.
-	for (i=0;i<nsounds;i++)
-		if (sounds[i]&&sounds[i]->filename&&
-			!strcasecmp(sounds[i]->filename,filename)) {
-			sounds[i]->uses++;
-			return sounds[i]->id;
-		}
-	// Ugh. Gotta load it. Being as loading the sound has no place at the
-	// implementation level, we're going to toss this over to the misc
-	// level.
-	moo=s_sound_loadfile(filename);
-	if (!moo) return -1;
-	moo->id=sound_id++;
-	moo->uses=1;
-	dpl_LINK(nsounds,sounds,moo,4,i);
-	return moo->id;
-}
-
-int i_sound_register_raw(struct Sound_t *moo) {
-	int i;
-	if (sound_fd<0||!moo) return -1;
-	moo->id=sound_id++;
-	moo->uses=1;
-	dpl_LINK(nsounds,sounds,moo,4,i);
-	return moo->id;
-}
-
-void i_sound_unregister(int id) {
-	int i;
-	if (sound_fd<0) return;
-	if (id<=0) return;
-	for (i=0;i<nsounds;i++) if (sounds[i]&&sounds[i]->id==id) {
-		// Let the program clean up properly.
-		if ((--sounds[i]->uses)>0) return;
-		
-		if (sounds[i]->data) m_free(sounds[i]->data,FALSE);
-		if (sounds[i]->filename) free(sounds[i]->filename);
-		free(sounds[i]);
-		sounds[i]=NULL;
-		return;
-	}
-}
-
-int i_sound_running(void) {
-	if (sound_fd<0) return 0;
-	return 1;
-}
-
-#endif
diff -urN phorus-0.9alpha6.orig/src/linux/i_sound.c phorus-0.9alpha6/src/linux/i_sound.c
--- phorus-0.9alpha6.orig/src/linux/i_sound.c	Thu Jan  1 01:00:00 1970
+++ phorus-0.9alpha6/src/linux/i_sound.c	Sun Dec  6 21:30:22 1998
@@ -0,0 +1,344 @@
+// Phorus
+//
+// i_sound.c
+//
+// Happyfun sound code.
+
+#include "phorus.h"
+#include "sound.h"
+
+static int sound_fd=-1;
+
+static struct Sound_t **sounds;
+static int nsounds;
+
+static struct SoundPlaying_t **sounds_playing;
+static int nsounds_playing;
+
+static int sound_id=1;
+
+#ifdef HAVE_ESD
+#include <dlfcn.h>
+#include <esd.h>
+#endif
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+
+static const int bitrates[4]={0,44100,88200,176400};
+static const int bufsizes[4]={512,1024,2048,4096};
+static const int passto[4]={10,11,12,13};
+
+static int sound_rate=-1;
+static int sound_bits=-1;
+static int sound_stereo=0;
+static int sound_bufsize=0;
+
+static char *sound_blankbuf=NULL;
+
+void i_sound_close(void) {
+	struct itimerval itime;
+
+	if (sound_fd<0) return;
+	// Kill off the timer.
+	itime.it_interval.tv_sec=0;
+	itime.it_interval.tv_usec=0;
+	itime.it_value.tv_sec=0;
+	itime.it_value.tv_usec=0;
+	if (setitimer(ITIMER_REAL,&itime,NULL)<0)
+		i_error(("setitimer failed with error: %s\n",strerror(errno)));
+
+	// Close the descriptor
+	close(sound_fd);
+	sound_fd=-1;
+}
+
+int i_sound_init(int rate, int bits, int stereo) {
+	struct sigaction sa;
+	struct itimerval itime;
+	int temp;
+	int bufdata=2;
+	int bitrate;
+	if (sound_fd>=0) i_sound_close();
+
+#ifdef HAVE_ESD
+	if (m_findarg("-esd")) do {
+		void *libesd;
+		int (*esd_playstream)(esd_format_t f, int r, char *h, char *n);
+		char *err;
+		int fmt;
+		// Whee.. ESD support it is, although it's a slowass piece
+		// of crap at anything but 44KHz/16bit/stereo
+		
+		// This won't work. I need some way of checking to see if
+		// there's anything in the buffer so I can have a nice, steady
+		// buffer flow that happens in /real time/.
+		
+		if (!(libesd=dlopen("libesd.so",RTLD_LAZY))) {
+			i_error(("Can't open libesd(%s). Falling back to regular sound.\n",
+				dlerror()));
+			break;
+		}
+		
+		esd_playstream=dlsym(libesd,"esd_play_stream");
+		if ((err=dlerror())) {
+			i_error(("Couldn't get esd_play_stream(%s), falling back to regular sound.\n",
+				err));
+			dlclose(libesd);
+			break;
+		}
+		fmt=((bits==8)?ESD_BITS8:0)|((stereo==0)?ESD_MONO:0)|ESD_STREAM|ESD_PLAY;
+		sound_fd=esd_playstream(fmt,rate,"","Phorus");
+		if (sound_fd<=0) {
+			sound_fd=-1;
+			i_error(("esd_play_stream failed. Falling back.\n"));
+			dlclose(libesd);
+			break;
+		}
+		// don't need libesd anymore...
+		dlclose(libesd);
+		i_printf(("Using ESD.\n"));
+	} while(0);
+#endif
+
+	if (sound_fd<0) {
+		if ((sound_fd=open("/dev/dsp",O_WRONLY,0))<0) {
+			i_printf(("i_sound_init: Couldn't open sound card. Disabling sound.\n"));
+			return 0;
+		}
+
+		if (fcntl(sound_fd,F_SETFL,O_NONBLOCK)<0) {
+			i_printf(("i_sound_init: Couldn't set nonblocking IO. Disabling sound.\n"));
+			i_sound_close();
+			return 0;
+		}
+	
+		if (ioctl(sound_fd,SNDCTL_DSP_SAMPLESIZE,&bits)<0) {
+			i_printf(("i_sound_init: Can't set sample size of %d. Disabling sound.\n"));
+			i_sound_close();
+			return 0;
+		}
+		if (stereo>0) stereo=1; else stereo=0;
+		if (ioctl(sound_fd,SNDCTL_DSP_STEREO,&stereo)<0) {
+			i_printf(("i_sound_init: Can't set mono/stereo. Disabling sound.\n"));
+			i_sound_close();
+			return 0;
+		}
+		if (ioctl(sound_fd,SNDCTL_DSP_SPEED,&rate)<0) {
+			i_printf(("i_sound_init: Can't set sound rate. Disabling sound.\n"));
+			i_sound_close();
+			return 0;
+		}
+		
+		bitrate=rate*(bits>>3)*(stereo+1);
+		
+		for (temp=0;temp<3;temp++)
+			if (bitrate>=bitrates[temp]&&bitrate<bitrates[temp+1])
+				break;
+		bufdata=temp;
+		
+		temp=passto[bufdata]|(3<<16);
+		if (ioctl(sound_fd,SNDCTL_DSP_SETFRAGMENT,&temp)<0) {
+			i_printf(("i_sound_init: Can't set fragment size of 1024. Disabling sound.\n"));
+			i_sound_close();
+			return 0;
+		}
+	}
+	
+	// Alright, now set the i_sound_update() timer.
+	// Also, fry the current abort(), whatever it may be. I'm not using
+	// it for anything anyway.
+	sa.sa_handler=(void *)i_sound_update;
+#ifdef SA_RESTART
+	sa.sa_flags=SA_RESTART;
+#else
+	sa.sa_flags=0;
+#endif
+	sigemptyset(&sa.sa_mask);
+	sigaction(SIGALRM,&sa,NULL);
+	
+	itime.it_interval.tv_sec=0;
+	itime.it_interval.tv_usec=10000;
+	itime.it_value.tv_sec=0;
+	itime.it_value.tv_usec=10000;
+	if (setitimer(ITIMER_REAL,&itime,NULL)<0)
+		i_error(("setitimer failed with error: %s\n",strerror(errno)));
+	
+	// No problems. *boggle*.
+	sound_rate=rate;
+	sound_bits=bits;
+	sound_stereo=stereo;
+
+	s_sound_mixat(rate,bits,stereo);
+	
+	sound_bufsize=bufsizes[bufdata];
+	
+	i_printf(("Sound enabled. Rate: %d  Bits: %d  %s  Bufsize: %d\n",
+		sound_rate,sound_bits,sound_stereo?"Stereo":"Mono",
+		sound_bufsize));
+	
+	if (sound_blankbuf) free(sound_blankbuf);
+	sound_blankbuf=malloc(sound_bufsize);
+	if (bits==8)
+		memset(sound_blankbuf,128,sound_bufsize);
+	else if (bits==16)
+		memset(sound_blankbuf,0,sound_bufsize);
+	return 1;
+}
+
+void i_sound_update(void) {
+	audio_buf_info ainfo;
+	int i,anysound=0;
+	char buf[8192];
+	if (sound_fd<0) return;
+	// Make sure there's enough room for our block.
+
+	if (ioctl(sound_fd,SNDCTL_DSP_GETOSPACE,&ainfo)<0||
+		ainfo.bytes<sound_bufsize)
+		return;
+	
+	// Well, we know there's a buffer update, so let the music stuff
+	// do it's thing.
+	s_mod_update(sound_bufsize);
+
+	for (i=0;i<nsounds_playing;i++) if (sounds_playing[i]) {
+		if (!anysound)
+			memset(buf,0,sound_bufsize*2);
+		anysound++;
+		// Mix to buffer..
+		s_sound_mix(buf,sound_bufsize,sounds_playing[i]);
+	}
+	
+	// Let's just call this one block for now.
+	if (anysound) {
+		// Final bounds check and tossage of everything
+		s_sound_finalmix(buf,sound_bufsize);
+		if (write(sound_fd,buf,sound_bufsize)!=sound_bufsize) {
+			i_error(("i_sound_init: Error writing to sound! Closing sound..\n"));
+			i_sound_close();
+			return;
+		}
+	} else {
+		if (write(sound_fd,sound_blankbuf,sound_bufsize)!=sound_bufsize) {
+			i_error(("i_sound_init: Error writing to sound! Closing sound..\n"));
+			i_sound_close();
+			return;
+		}
+	}
+}
+
+#else /* HAVE_SYS_SOUNDCARD_H */
+
+void i_sound_close(void)
+{
+}
+
+int i_sound_init(int rate, int bits, int stereo)
+{
+	return 0;
+}
+
+void i_sound_update(void)
+{
+}
+
+#endif /* HAVE_SYS_SOUNDCARD_H */
+
+int i_sound_play(int soundnum, int vol, int pan, float delta, int flags) {
+	struct SoundPlaying_t *cow;
+	int i;
+	if (sound_fd<0||vol<=0||delta<=0.0) return -1;
+	for (i=0;i<nsounds;i++) if (sounds[i]&&sounds[i]->id==soundnum)
+		break;
+	if (i==nsounds) return -1;
+	if (vol>255) vol=255;
+	if (pan<-128) pan=-128;
+	if (pan>127) pan=127;
+	
+	cow=calloc(1,sizeof(struct SoundPlaying_t));
+	cow->sound=sounds[i];
+	cow->point=0;
+	cow->volume=vol;
+	cow->pan=pan;
+	cow->delta=(int)((float)sounds[i]->delta*delta);
+	cow->flags=flags|sounds[i]->flags;
+	cow->len=sounds[i]->len;
+	cow->id=sound_id++;
+	dpl_LINK(nsounds_playing,sounds_playing,cow,4,i);
+	return cow->id;
+}
+
+void i_sound_stop(int id) {
+	int i;
+	
+	if (id<=0) return;
+	
+	for (i=0;i<nsounds_playing;i++)
+		if (sounds_playing[i]&&sounds_playing[i]->id==id) {
+			free(sounds_playing[i]);
+			sounds_playing[i]=NULL;
+			return;
+		}
+}
+
+struct SoundPlaying_t *i_sound_playing_get(int id) {
+	int i;
+	if (id<=0) return NULL;
+	for (i=0;i<nsounds_playing;i++)
+		if (sounds_playing[i]&&sounds_playing[i]->id==id)
+			return sounds_playing[i];
+	return NULL;
+}
+
+int i_sound_register_file(char *filename) {
+	struct Sound_t *moo;
+	int i;
+	if (sound_fd<0) return -1;
+	// First check loaded sounds to see if this one's been loaded already.
+	for (i=0;i<nsounds;i++)
+		if (sounds[i]&&sounds[i]->filename&&
+			!strcasecmp(sounds[i]->filename,filename)) {
+			sounds[i]->uses++;
+			return sounds[i]->id;
+		}
+	// Ugh. Gotta load it. Being as loading the sound has no place at the
+	// implementation level, we're going to toss this over to the misc
+	// level.
+	moo=s_sound_loadfile(filename);
+	if (!moo) return -1;
+	moo->id=sound_id++;
+	moo->uses=1;
+	dpl_LINK(nsounds,sounds,moo,4,i);
+	return moo->id;
+}
+
+int i_sound_register_raw(struct Sound_t *moo) {
+	int i;
+	if (sound_fd<0||!moo) return -1;
+	moo->id=sound_id++;
+	moo->uses=1;
+	dpl_LINK(nsounds,sounds,moo,4,i);
+	return moo->id;
+}
+
+void i_sound_unregister(int id) {
+	int i;
+	if (sound_fd<0) return;
+	if (id<=0) return;
+	for (i=0;i<nsounds;i++) if (sounds[i]&&sounds[i]->id==id) {
+		// Let the program clean up properly.
+		if ((--sounds[i]->uses)>0) return;
+		
+		if (sounds[i]->data) m_free(sounds[i]->data,FALSE);
+		if (sounds[i]->filename) free(sounds[i]->filename);
+		free(sounds[i]);
+		sounds[i]=NULL;
+		return;
+	}
+}
+
+int i_sound_running(void) {
+	if (sound_fd<0) return 0;
+	return 1;
+}
