Added Linux PlayStation 2 Graphics Synthesizer support
authorSam Lantinga <slouken@lokigames.com>
Sat, 16 Jun 2001 03:17:45 +0000
changeset 70 f590dd383b5d
parent 69 280ff3af2ecc
child 71 cb4d780b41b6
Added Linux PlayStation 2 Graphics Synthesizer support
configure.in
docs.html
src/video/ps2gs/.cvsignore
src/video/ps2gs/Makefile.am
src/video/ps2gs/SDL_gsevents.c
src/video/ps2gs/SDL_gsevents_c.h
src/video/ps2gs/SDL_gskeys.h
src/video/ps2gs/SDL_gsmouse.c
src/video/ps2gs/SDL_gsmouse_c.h
src/video/ps2gs/SDL_gsvideo.c
src/video/ps2gs/SDL_gsvideo.h
src/video/ps2gs/SDL_gsyuv.c
src/video/ps2gs/SDL_gsyuv_c.h
--- a/configure.in	Sat Jun 16 02:48:39 2001 +0000
+++ b/configure.in	Sat Jun 16 03:17:45 2001 +0000
@@ -666,6 +666,32 @@
     fi
 }
 
+dnl See if we're running on PlayStation 2 hardware
+CheckPS2GS()
+{
+dnl    AC_ARG_ENABLE(video-ps2gs,
+dnl[  --enable-video-ps2gs    use PlayStation 2 GS video driver [default=yes]],
+dnl                  , enable_video_ps2gs=yes)
+enable_video_ps2gs=yes
+    if test x$enable_video = xyes -a x$enable_video_ps2gs = xyes; then
+        dnl AC_MSG_CHECKING(for PlayStation 2 GS support)
+        video_ps2gs=no
+        AC_TRY_COMPILE([
+         #include <linux/ps2/dev.h>
+         #include <linux/ps2/gs.h>
+        ],[
+        ],[
+        video_ps2gs=yes
+        ])
+        dnl AC_MSG_RESULT($video_ps2gs)
+        if test x$video_ps2gs = xyes; then
+            CFLAGS="$CFLAGS -DENABLE_PS2GS"
+            VIDEO_SUBDIRS="$VIDEO_SUBDIRS ps2gs"
+            VIDEO_DRIVERS="$VIDEO_DRIVERS ps2gs/libvideo_ps2gs.la"
+        fi
+    fi
+}
+
 dnl Find the GGI includes
 CheckGGI()
 {
@@ -1111,6 +1137,7 @@
         CheckNANOX
         CheckDGA
         CheckFBCON
+        CheckPS2GS
         CheckGGI
         CheckSVGA
         CheckAAlib
@@ -2011,6 +2038,7 @@
 src/video/dga/Makefile
 src/video/nanox/Makefile
 src/video/fbcon/Makefile
+src/video/ps2gs/Makefile
 src/video/ggi/Makefile
 src/video/maccommon/Makefile
 src/video/macdsp/Makefile
--- a/docs.html	Sat Jun 16 02:48:39 2001 +0000
+++ b/docs.html	Sat Jun 16 03:17:45 2001 +0000
@@ -16,6 +16,7 @@
 Major changes since SDL 1.0.0:
 </H2>
 <UL>
+	<LI> 1.2.1: Added Linux PlayStation 2 Graphics Synthesizer support
 	<LI> 1.2.1: Added an audio driver that writes to disk (thanks Ryan!)
 	<LI> 1.2.1: Mouse wheel sends mouse button (4/5) events on Windows
 	<LI> 1.2.1: Added MacOS X Project Builder projects (thanks Darrell!)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/.cvsignore	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,6 @@
+Makefile.in
+Makefile
+.libs
+*.o
+*.lo
+*.la
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/Makefile.am	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,17 @@
+
+## Makefile.am for SDL using the framebuffer console video driver
+
+noinst_LTLIBRARIES = libvideo_ps2gs.la
+libvideo_ps2gs_la_SOURCES = $(PS2GS_SRCS)
+
+# The SDL framebuffer console video driver sources
+PS2GS_SRCS = 			\
+	SDL_gsevents.c		\
+	SDL_gsevents_c.h	\
+	SDL_gskeys.h		\
+	SDL_gsmouse.c		\
+	SDL_gsmouse_c.h		\
+	SDL_gsvideo.c		\
+	SDL_gsvideo.h		\
+	SDL_gsyuv.c		\
+	SDL_gsyuv_c.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsevents.c	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,983 @@
+/*
+	SDL - Simple DirectMedia Layer
+	Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
+
+	This library is free software; you can redistribute it and/or
+	modify it under the terms of the GNU Library General Public
+	License as published by the Free Software Foundation; either
+	version 2 of the License, or (at your option) any later version.
+
+	This library 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
+	Library General Public License for more details.
+
+	You should have received a copy of the GNU Library General Public
+	License along with this library; if not, write to the Free
+	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+	Sam Lantinga
+	slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* Handle the event stream, converting console events into SDL events */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+/* For parsing /proc */
+#include <dirent.h>
+#include <ctype.h>
+
+#include <linux/vt.h>
+#include <linux/kd.h>
+#include <linux/keyboard.h>
+
+#include "SDL.h"
+#include "SDL_mutex.h"
+#include "SDL_sysevents.h"
+#include "SDL_sysvideo.h"
+#include "SDL_events_c.h"
+#include "SDL_gsvideo.h"
+#include "SDL_gsevents_c.h"
+#include "SDL_gskeys.h"
+
+#ifndef GPM_NODE_FIFO
+#define GPM_NODE_FIFO	"/dev/gpmdata"
+#endif
+
+/* The translation tables from a console scancode to a SDL keysym */
+#define NUM_VGAKEYMAPS	(1<<KG_CAPSSHIFT)
+static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
+static SDLKey keymap[128];
+static Uint16 keymap_temp[128]; /* only used at startup */
+static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);
+
+/* Ugh, we have to duplicate the kernel's keysym mapping code...
+   Oh, it's not so bad. :-)
+
+   FIXME: Add keyboard LED handling code
+ */
+static void GS_vgainitkeymaps(int fd)
+{
+	struct kbentry entry;
+	int map, i;
+
+	/* Don't do anything if we are passed a closed keyboard */
+	if ( fd < 0 ) {
+		return;
+	}
+
+	/* Load all the keysym mappings */
+	for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {
+		memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));
+		for ( i=0; i<NR_KEYS; ++i ) {
+			entry.kb_table = map;
+			entry.kb_index = i;
+			if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {
+				/* fill keytemp. This replaces SDL_fbkeys.h */
+				if ( (map == 0) && (i<128) ) {
+					keymap_temp[i] = entry.kb_value;
+				}
+				/* The "Enter" key is a special case */
+				if ( entry.kb_value == K_ENTER ) {
+					entry.kb_value = K(KT_ASCII,13);
+				}
+				/* Handle numpad specially as well */
+				if ( KTYP(entry.kb_value) == KT_PAD ) {
+					switch ( entry.kb_value ) {
+					case K_P0:
+					case K_P1:
+					case K_P2:
+					case K_P3:
+					case K_P4:
+					case K_P5:
+					case K_P6:
+					case K_P7:
+					case K_P8:
+					case K_P9:
+						vga_keymap[map][i]=entry.kb_value;
+						vga_keymap[map][i]+= '0';
+						break;
+										case K_PPLUS:
+						vga_keymap[map][i]=K(KT_ASCII,'+');
+						break;
+										case K_PMINUS:
+						vga_keymap[map][i]=K(KT_ASCII,'-');
+						break;
+										case K_PSTAR:
+						vga_keymap[map][i]=K(KT_ASCII,'*');
+						break;
+										case K_PSLASH:
+						vga_keymap[map][i]=K(KT_ASCII,'/');
+						break;
+										case K_PENTER:
+						vga_keymap[map][i]=K(KT_ASCII,'\r');
+						break;
+										case K_PCOMMA:
+						vga_keymap[map][i]=K(KT_ASCII,',');
+						break;
+										case K_PDOT:
+						vga_keymap[map][i]=K(KT_ASCII,'.');
+						break;
+					default:
+						break;
+					}
+				}
+				/* Do the normal key translation */
+				if ( (KTYP(entry.kb_value) == KT_LATIN) ||
+					 (KTYP(entry.kb_value) == KT_ASCII) ||
+					 (KTYP(entry.kb_value) == KT_LETTER) ) {
+					vga_keymap[map][i] = entry.kb_value;
+				}
+			}
+		}
+	}
+}
+
+int GS_InGraphicsMode(_THIS)
+{
+	return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
+}
+
+int GS_EnterGraphicsMode(_THIS)
+{
+	struct termios keyboard_termios;
+
+	/* Set medium-raw keyboard mode */
+	if ( (keyboard_fd >= 0) && !GS_InGraphicsMode(this) ) {
+
+		/* Switch to the correct virtual terminal */
+		if ( current_vt > 0 ) {
+			struct vt_stat vtstate;
+
+			if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {
+				saved_vt = vtstate.v_active;
+			}
+			if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) {
+				ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
+			}
+		}
+
+		/* Set the terminal input mode */
+		if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {
+			SDL_SetError("Unable to get terminal attributes");
+			if ( keyboard_fd > 0 ) {
+				close(keyboard_fd);
+			}
+			keyboard_fd = -1;
+			return(-1);
+		}
+		if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {
+			SDL_SetError("Unable to get current keyboard mode");
+			if ( keyboard_fd > 0 ) {
+				close(keyboard_fd);
+			}
+			keyboard_fd = -1;
+			return(-1);
+		}
+		keyboard_termios = saved_kbd_termios;
+		keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
+		keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
+		keyboard_termios.c_cc[VMIN] = 0;
+		keyboard_termios.c_cc[VTIME] = 0;
+		if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
+			GS_CloseKeyboard(this);
+			SDL_SetError("Unable to set terminal attributes");
+			return(-1);
+		}
+		/* This will fail if we aren't root or this isn't our tty */
+		if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {
+			GS_CloseKeyboard(this);
+			SDL_SetError("Unable to set keyboard in raw mode");
+			return(-1);
+		}
+		if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {
+			GS_CloseKeyboard(this);
+			SDL_SetError("Unable to set keyboard in graphics mode");
+			return(-1);
+		}
+	}
+	return(keyboard_fd);
+}
+
+void GS_LeaveGraphicsMode(_THIS)
+{
+	if ( GS_InGraphicsMode(this) ) {
+		ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
+		ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
+		tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
+		saved_kbd_mode = -1;
+
+		/* Head back over to the original virtual terminal */
+		if ( saved_vt > 0 ) {
+			ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
+		}
+	}
+}
+
+void GS_CloseKeyboard(_THIS)
+{
+	if ( keyboard_fd >= 0 ) {
+		GS_LeaveGraphicsMode(this);
+		if ( keyboard_fd > 0 ) {
+			close(keyboard_fd);
+		}
+	}
+	keyboard_fd = -1;
+}
+
+int GS_OpenKeyboard(_THIS)
+{
+	/* Open only if not already opened */
+ 	if ( keyboard_fd < 0 ) {
+		char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
+		char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
+		int i, tty0_fd;
+
+		/* Try to query for a free virtual terminal */
+		tty0_fd = -1;
+		for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
+			tty0_fd = open(tty0[i], O_WRONLY, 0);
+		}
+		if ( tty0_fd < 0 ) {
+			tty0_fd = dup(0); /* Maybe stdin is a VT? */
+		}
+		ioctl(tty0_fd, VT_OPENQRY, &current_vt);
+		close(tty0_fd);
+		if ( (geteuid() == 0) && (current_vt > 0) ) {
+			for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) {
+				char vtpath[12];
+
+				sprintf(vtpath, vcs[i], current_vt);
+				keyboard_fd = open(vtpath, O_RDWR, 0);
+#ifdef DEBUG_KEYBOARD
+				fprintf(stderr, "vtpath = %s, fd = %d\n",
+					vtpath, keyboard_fd);
+#endif /* DEBUG_KEYBOARD */
+
+				/* This needs to be our controlling tty
+				   so that the kernel ioctl() calls work
+				*/
+				if ( keyboard_fd >= 0 ) {
+					tty0_fd = open("/dev/tty", O_RDWR, 0);
+					if ( tty0_fd >= 0 ) {
+						ioctl(tty0_fd, TIOCNOTTY, 0);
+						close(tty0_fd);
+					}
+				}
+			}
+		}
+ 		if ( keyboard_fd < 0 ) {
+			/* Last resort, maybe our tty is a usable VT */
+			current_vt = 0;
+			keyboard_fd = open("/dev/tty", O_RDWR);
+ 		}
+#ifdef DEBUG_KEYBOARD
+		fprintf(stderr, "Current VT: %d\n", current_vt);
+#endif
+ 		saved_kbd_mode = -1;
+
+		/* Make sure that our input is a console terminal */
+		{ int dummy;
+		  if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {
+			close(keyboard_fd);
+			keyboard_fd = -1;
+			SDL_SetError("Unable to open a console terminal");
+		  }
+		}
+
+		/* Set up keymap */
+		GS_vgainitkeymaps(keyboard_fd);
+ 	}
+ 	return(keyboard_fd);
+}
+
+static enum {
+	MOUSE_NONE = -1,
+	MOUSE_GPM,	/* Note: GPM uses the MSC protocol */
+	MOUSE_PS2,
+	MOUSE_IMPS2,
+	MOUSE_MS,
+	MOUSE_BM,
+	NUM_MOUSE_DRVS
+} mouse_drv = MOUSE_NONE;
+
+void GS_CloseMouse(_THIS)
+{
+	if ( mouse_fd > 0 ) {
+		close(mouse_fd);
+	}
+	mouse_fd = -1;
+}
+
+/* Returns processes listed in /proc with the desired name */
+static int find_pid(DIR *proc, const char *wanted_name)
+{
+	struct dirent *entry;
+	int pid;
+
+	/* First scan proc for the gpm process */
+	pid = 0;
+	while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {
+		if ( isdigit(entry->d_name[0]) ) {
+			FILE *status;
+			char path[PATH_MAX];
+			char name[PATH_MAX];
+
+			sprintf(path, "/proc/%s/status", entry->d_name);
+			status=fopen(path, "r");
+			if ( status ) {
+				name[0] = '\0';
+				fscanf(status, "Name: %s", name);
+				if ( strcmp(name, wanted_name) == 0 ) {
+					pid = atoi(entry->d_name);
+				}
+				fclose(status);
+			}
+		}
+	}
+	return pid;
+}
+
+/* Returns true if /dev/gpmdata is being written to by gpm */
+static int gpm_available(void)
+{
+	int available;
+	DIR *proc;
+	int pid;
+	int cmdline, len, arglen;
+	char path[PATH_MAX];
+	char args[PATH_MAX], *arg;
+
+	/* Don't bother looking if the fifo isn't there */
+	if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {
+		return(0);
+	}
+
+	available = 0;
+	proc = opendir("/proc");
+	if ( proc ) {
+		while ( (pid=find_pid(proc, "gpm")) > 0 ) {
+			sprintf(path, "/proc/%d/cmdline", pid);
+			cmdline = open(path, O_RDONLY, 0);
+			if ( cmdline >= 0 ) {
+				len = read(cmdline, args, sizeof(args));
+				arg = args;
+				while ( len > 0 ) {
+					if ( strcmp(arg, "-R") == 0 ) {
+						available = 1;
+					}
+					arglen = strlen(arg)+1;
+					len -= arglen;
+					arg += arglen;
+				}
+				close(cmdline);
+			}
+		}
+		closedir(proc);
+	}
+	return available;
+}
+
+
+/* rcg06112001 Set up IMPS/2 mode, if possible. This gives
+ *  us access to the mousewheel, etc. Returns zero if
+ *  writes to device failed, but you still need to query the
+ *  device to see which mode it's actually in.
+ */
+static int set_imps2_mode(int fd)
+{
+	/* If you wanted to control the mouse mode (and we do :)  ) ...
+		Set IMPS/2 protocol:
+			{0xf3,200,0xf3,100,0xf3,80}
+		Reset mouse device:
+			{0xFF}
+	*/
+	Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
+	Uint8 reset = 0xff;
+	fd_set fdset;
+	struct timeval tv;
+	int retval = 0;
+
+	if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
+		if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
+			retval = 1;
+		}
+	}
+
+	/* Get rid of any chatter from the above */
+	FD_ZERO(&fdset);
+	FD_SET(fd, &fdset);
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+	while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
+		char temp[32];
+		read(fd, temp, sizeof(temp));
+	}
+
+	return retval;
+}
+
+
+/* Returns true if the mouse uses the IMPS/2 protocol */
+static int detect_imps2(int fd)
+{
+	int imps2;
+
+	imps2 = 0;
+
+	if ( getenv("SDL_MOUSEDEV_IMPS2") ) {
+		imps2 = 1;
+	}
+	if ( ! imps2 ) {
+		Uint8 query_ps2 = 0xF2;
+		fd_set fdset;
+		struct timeval tv;
+
+		/* Get rid of any mouse motion noise */
+		FD_ZERO(&fdset);
+		FD_SET(fd, &fdset);
+		tv.tv_sec = 0;
+		tv.tv_usec = 0;
+		while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
+			char temp[32];
+			read(fd, temp, sizeof(temp));
+		}
+
+   		/* Query for the type of mouse protocol */
+   		if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
+   			Uint8 ch = 0;
+
+			/* Get the mouse protocol response */
+			do {
+				FD_ZERO(&fdset);
+				FD_SET(fd, &fdset);
+				tv.tv_sec = 1;
+				tv.tv_usec = 0;
+				if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) {
+					break;
+				}
+			} while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&
+			          ((ch == 0xFA) || (ch == 0xAA)) );
+
+			/* Experimental values (Logitech wheelmouse) */
+#ifdef DEBUG_MOUSE
+fprintf(stderr, "Last mouse mode: 0x%x\n", ch);
+#endif
+			if ( ch == 3 ) {
+				imps2 = 1;
+			}
+		}
+	}
+	return imps2;
+}
+
+int GS_OpenMouse(_THIS)
+{
+	int i;
+	const char *mousedev;
+	const char *mousedrv;
+
+	mousedrv = getenv("SDL_MOUSEDRV");
+	mousedev = getenv("SDL_MOUSEDEV");
+	mouse_fd = -1;
+
+	/* STD MICE */
+
+	if ( mousedev == NULL ) {
+		/* FIXME someday... allow multiple mice in this driver */
+		char *ps2mice[] = {
+		    "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
+		};
+		/* First try to use GPM in repeater mode */
+		if ( mouse_fd < 0 ) {
+			if ( gpm_available() ) {
+				mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0);
+				if ( mouse_fd >= 0 ) {
+#ifdef DEBUG_MOUSE
+fprintf(stderr, "Using GPM mouse\n");
+#endif
+					mouse_drv = MOUSE_GPM;
+				}
+			}
+		}
+		/* Now try to use a modern PS/2 mouse */
+		for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) {
+			mouse_fd = open(ps2mice[i], O_RDWR, 0);
+			if (mouse_fd < 0) {
+				mouse_fd = open(ps2mice[i], O_RDONLY, 0);
+			}
+			if (mouse_fd >= 0) {
+				/* rcg06112001 Attempt to set IMPS/2 mode */
+				if ( i == 0 ) {
+					set_imps2_mode(mouse_fd);
+				}
+				if (detect_imps2(mouse_fd)) {
+#ifdef DEBUG_MOUSE
+fprintf(stderr, "Using IMPS2 mouse\n");
+#endif
+					mouse_drv = MOUSE_IMPS2;
+				} else {
+					mouse_drv = MOUSE_PS2;
+#ifdef DEBUG_MOUSE
+fprintf(stderr, "Using PS2 mouse\n");
+#endif
+				}
+			}
+		}
+		/* Next try to use a PPC ADB port mouse */
+		if ( mouse_fd < 0 ) {
+			mouse_fd = open("/dev/adbmouse", O_RDONLY, 0);
+			if ( mouse_fd >= 0 ) {
+#ifdef DEBUG_MOUSE
+fprintf(stderr, "Using ADB mouse\n");
+#endif
+				mouse_drv = MOUSE_BM;
+			}
+		}
+	}
+	/* Default to a serial Microsoft mouse */
+	if ( mouse_fd < 0 ) {
+		if ( mousedev == NULL ) {
+			mousedev = "/dev/mouse";
+		}
+		mouse_fd = open(mousedev, O_RDONLY, 0);
+		if ( mouse_fd >= 0 ) {
+			struct termios mouse_termios;
+
+			/* Set the sampling speed to 1200 baud */
+			tcgetattr(mouse_fd, &mouse_termios);
+			mouse_termios.c_iflag = IGNBRK | IGNPAR;
+			mouse_termios.c_oflag = 0;
+			mouse_termios.c_lflag = 0;
+			mouse_termios.c_line = 0;
+			mouse_termios.c_cc[VTIME] = 0;
+			mouse_termios.c_cc[VMIN] = 1;
+			mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
+			mouse_termios.c_cflag |= CS8;
+			mouse_termios.c_cflag |= B1200;
+			tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios);
+#ifdef DEBUG_MOUSE
+fprintf(stderr, "Using Microsoft mouse on %s\n", mousedev);
+#endif
+			mouse_drv = MOUSE_MS;
+		}
+	}
+	if ( mouse_fd < 0 ) {
+		mouse_drv = MOUSE_NONE;
+	}
+	return(mouse_fd);
+}
+
+static int posted = 0;
+
+void GS_vgamousecallback(int button, int dx, int dy)
+{
+	int button_1, button_3;
+	int button_state;
+	int state_changed;
+	int i;
+	Uint8 state;
+
+	if ( dx || dy ) {
+		posted += SDL_PrivateMouseMotion(0, 1, dx, dy);
+	}
+
+	/* Swap button 1 and 3 */
+	button_1 = (button & 0x04) >> 2;
+	button_3 = (button & 0x01) << 2;
+	button &= ~0x05;
+	button |= (button_1|button_3);
+
+	/* See what changed */
+	button_state = SDL_GetMouseState(NULL, NULL);
+	state_changed = button_state ^ button;
+	for ( i=0; i<8; ++i ) {
+		if ( state_changed & (1<<i) ) {
+			if ( button & (1<<i) ) {
+				state = SDL_PRESSED;
+			} else {
+				state = SDL_RELEASED;
+			}
+			posted += SDL_PrivateMouseButton(state, i+1, 0, 0);
+		}
+	}
+}
+
+/* For now, use GPM, PS/2, and MS protocols
+   Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
+ */
+static void handle_mouse(_THIS)
+{
+	static int start = 0;
+	static unsigned char mousebuf[BUFSIZ];
+	int i, nread;
+	int button = 0;
+	int dx = 0, dy = 0;
+	int packetsize = 0;
+
+	/* Figure out the mouse packet size */
+	switch (mouse_drv) {
+		case MOUSE_NONE:
+			/* Ack! */
+			read(mouse_fd, mousebuf, BUFSIZ);
+			return;
+		case MOUSE_GPM:
+			packetsize = 5;
+			break;
+		case MOUSE_IMPS2:
+			packetsize = 4;
+			break;
+		case MOUSE_PS2:
+		case MOUSE_MS:
+		case MOUSE_BM:
+			packetsize = 3;
+			break;
+		case NUM_MOUSE_DRVS:
+			/* Uh oh.. */
+			packetsize = 0;
+			break;
+	}
+
+	/* Read as many packets as possible */
+	nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start);
+	if ( nread < 0 ) {
+		return;
+	}
+	nread += start;
+#ifdef DEBUG_MOUSE
+	fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
+#endif
+	for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) {
+		switch (mouse_drv) {
+			case MOUSE_NONE:
+				break;
+			case MOUSE_GPM:
+				/* GPM protocol has 0x80 in high byte */
+				if ( (mousebuf[i] & 0xF8) != 0x80 ) {
+					/* Go to next byte */
+					i -= (packetsize-1);
+					continue;
+				}
+				/* Get current mouse state */
+				button = (~mousebuf[i]) & 0x07;
+				dx =   (signed char)(mousebuf[i+1]) +
+				       (signed char)(mousebuf[i+3]);
+				dy = -((signed char)(mousebuf[i+2]) +
+				       (signed char)(mousebuf[i+4]));
+				break;
+			case MOUSE_PS2:
+				/* PS/2 protocol has nothing in high byte */
+				if ( (mousebuf[i] & 0xC0) != 0 ) {
+					/* Go to next byte */
+					i -= (packetsize-1);
+					continue;
+				}
+				/* Get current mouse state */
+				button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
+		  			 (mousebuf[i] & 0x02) >> 1 | /*Right*/
+		  			 (mousebuf[i] & 0x01) << 2;  /*Left*/
+		  		dx = (mousebuf[i] & 0x10) ?
+		  		      mousebuf[i+1] - 256 : mousebuf[i+1];
+		  		dy = (mousebuf[i] & 0x20) ?
+		  		      -(mousebuf[i+2] - 256) : -mousebuf[i+2];
+				break;
+			case MOUSE_IMPS2:
+				/* Get current mouse state */
+				button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
+		  			 (mousebuf[i] & 0x02) >> 1 | /*Right*/
+		  			 (mousebuf[i] & 0x01) << 2 | /*Left*/
+		  			 (mousebuf[i] & 0x40) >> 3 | /* 4 */
+		  			 (mousebuf[i] & 0x80) >> 3;  /* 5 */
+		  		dx = (mousebuf[i] & 0x10) ?
+		  		      mousebuf[i+1] - 256 : mousebuf[i+1];
+		  		dy = (mousebuf[i] & 0x20) ?
+		  		      -(mousebuf[i+2] - 256) : -mousebuf[i+2];
+				switch (mousebuf[i+3]&0x0F) {
+				    case 0x0E: /* DX = +1 */
+				    case 0x02: /* DX = -1 */
+					break;
+				    case 0x0F: /* DY = +1 (map button 4) */
+					button |= (1<<3);
+					break;
+				    case 0x01: /* DY = -1 (map button 5) */
+					button |= (1<<4);
+					break;
+				}
+				break;
+			case MOUSE_MS:
+				/* Microsoft protocol has 0x40 in high byte */
+				if ( (mousebuf[i] & 0x40) != 0x40 ) {
+					/* Go to next byte */
+					i -= (packetsize-1);
+					continue;
+				}
+				/* Get current mouse state */
+				button = ((mousebuf[i] & 0x20) >> 3) |
+				         ((mousebuf[i] & 0x10) >> 4);
+				dx = (signed char)(((mousebuf[i] & 0x03) << 6) |
+				                   (mousebuf[i + 1] & 0x3F));
+				dy = (signed char)(((mousebuf[i] & 0x0C) << 4) |
+				                    (mousebuf[i + 2] & 0x3F));
+				break;
+			case MOUSE_BM:
+				/* BusMouse protocol has 0xF8 in high byte */
+				if ( (mousebuf[i] & 0xF8) != 0x80 ) {
+					/* Go to next byte */
+					i -= (packetsize-1);
+					continue;
+				}
+				/* Get current mouse state */
+				button = (~mousebuf[i]) & 0x07;
+				dx =  (signed char)mousebuf[i+1];
+				dy = -(signed char)mousebuf[i+2];
+				break;
+			case NUM_MOUSE_DRVS:
+				/* Uh oh.. */
+				dx = 0;
+				dy = 0;
+				break;
+		}
+		GS_vgamousecallback(button, dx, dy);
+	}
+	if ( i < nread ) {
+		memcpy(mousebuf, &mousebuf[i], (nread-i));
+		start = (nread-i);
+	} else {
+		start = 0;
+	}
+	return;
+}
+
+static void handle_keyboard(_THIS)
+{
+	unsigned char keybuf[BUFSIZ];
+	int i, nread;
+	int pressed;
+	int scancode;
+	SDL_keysym keysym;
+
+	nread = read(keyboard_fd, keybuf, BUFSIZ);
+	for ( i=0; i<nread; ++i ) {
+		scancode = keybuf[i] & 0x7F;
+		if ( keybuf[i] & 0x80 ) {
+			pressed = SDL_RELEASED;
+		} else {
+			pressed = SDL_PRESSED;
+		}
+		TranslateKey(scancode, &keysym);
+		posted += SDL_PrivateKeyboard(pressed, &keysym);
+	}
+}
+
+void GS_PumpEvents(_THIS)
+{
+	fd_set fdset;
+	int max_fd;
+	static struct timeval zero;
+
+	do {
+		posted = 0;
+
+		FD_ZERO(&fdset);
+		max_fd = 0;
+		if ( keyboard_fd >= 0 ) {
+			FD_SET(keyboard_fd, &fdset);
+			if ( max_fd < keyboard_fd ) {
+				max_fd = keyboard_fd;
+			}
+		}
+		if ( mouse_fd >= 0 ) {
+			FD_SET(mouse_fd, &fdset);
+			if ( max_fd < mouse_fd ) {
+				max_fd = mouse_fd;
+			}
+		}
+		if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) {
+			if ( keyboard_fd >= 0 ) {
+				if ( FD_ISSET(keyboard_fd, &fdset) ) {
+					handle_keyboard(this);
+				}
+			}
+			if ( mouse_fd >= 0 ) {
+				if ( FD_ISSET(mouse_fd, &fdset) ) {
+					handle_mouse(this);
+				}
+			}
+		}
+	} while ( posted );
+}
+
+void GS_InitOSKeymap(_THIS)
+{
+	int i;
+
+	/* Initialize the Linux key translation table */
+
+	/* First get the ascii keys and others not well handled */
+	for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
+	  switch(i) {
+	  /* These aren't handled by the x86 kernel keymapping (?) */
+	  case SCANCODE_PRINTSCREEN:
+	    keymap[i] = SDLK_PRINT;
+	    break;
+	  case SCANCODE_BREAK:
+	    keymap[i] = SDLK_BREAK;
+	    break;
+	  case SCANCODE_BREAK_ALTERNATIVE:
+	    keymap[i] = SDLK_PAUSE;
+	    break;
+	  case SCANCODE_LEFTSHIFT:
+	    keymap[i] = SDLK_LSHIFT;
+	    break;
+	  case SCANCODE_RIGHTSHIFT:
+	    keymap[i] = SDLK_RSHIFT;
+	    break;
+	  case SCANCODE_LEFTCONTROL:
+	    keymap[i] = SDLK_LCTRL;
+	    break;
+	  case SCANCODE_RIGHTCONTROL:
+	    keymap[i] = SDLK_RCTRL;
+	    break;
+	  case SCANCODE_RIGHTWIN:
+	    keymap[i] = SDLK_RSUPER;
+	    break;
+	  case SCANCODE_LEFTWIN:
+	    keymap[i] = SDLK_LSUPER;
+	    break;
+	  case 127:
+	    keymap[i] = SDLK_MENU;
+	    break;
+	  /* this should take care of all standard ascii keys */
+	  default:
+	    keymap[i] = KVAL(vga_keymap[0][i]);
+	    break;
+          }
+	}
+	for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
+	  switch(keymap_temp[i]) {
+	    case K_F1:  keymap[i] = SDLK_F1;  break;
+	    case K_F2:  keymap[i] = SDLK_F2;  break;
+	    case K_F3:  keymap[i] = SDLK_F3;  break;
+	    case K_F4:  keymap[i] = SDLK_F4;  break;
+	    case K_F5:  keymap[i] = SDLK_F5;  break;
+	    case K_F6:  keymap[i] = SDLK_F6;  break;
+	    case K_F7:  keymap[i] = SDLK_F7;  break;
+	    case K_F8:  keymap[i] = SDLK_F8;  break;
+	    case K_F9:  keymap[i] = SDLK_F9;  break;
+	    case K_F10: keymap[i] = SDLK_F10; break;
+	    case K_F11: keymap[i] = SDLK_F11; break;
+	    case K_F12: keymap[i] = SDLK_F12; break;
+
+	    case K_DOWN:  keymap[i] = SDLK_DOWN;  break;
+	    case K_LEFT:  keymap[i] = SDLK_LEFT;  break;
+	    case K_RIGHT: keymap[i] = SDLK_RIGHT; break;
+	    case K_UP:    keymap[i] = SDLK_UP;    break;
+
+	    case K_P0:     keymap[i] = SDLK_KP0; break;
+	    case K_P1:     keymap[i] = SDLK_KP1; break;
+	    case K_P2:     keymap[i] = SDLK_KP2; break;
+	    case K_P3:     keymap[i] = SDLK_KP3; break;
+	    case K_P4:     keymap[i] = SDLK_KP4; break;
+	    case K_P5:     keymap[i] = SDLK_KP5; break;
+	    case K_P6:     keymap[i] = SDLK_KP6; break;
+	    case K_P7:     keymap[i] = SDLK_KP7; break;
+	    case K_P8:     keymap[i] = SDLK_KP8; break;
+	    case K_P9:     keymap[i] = SDLK_KP9; break;
+	    case K_PPLUS:  keymap[i] = SDLK_KP_PLUS; break;
+	    case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break;
+	    case K_PSTAR:  keymap[i] = SDLK_KP_MULTIPLY; break;
+	    case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break;
+	    case K_PENTER: keymap[i] = SDLK_KP_ENTER; break;
+	    case K_PDOT:   keymap[i] = SDLK_KP_PERIOD; break;
+
+	    case K_SHIFT:  if ( keymap[i] != SDLK_RSHIFT )
+	                     keymap[i] = SDLK_LSHIFT;
+	                   break;
+	    case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break;
+	    case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break;
+	    case K_CTRL:  if ( keymap[i] != SDLK_RCTRL )
+	                     keymap[i] = SDLK_LCTRL;
+	                   break;
+	    case K_CTRLL:  keymap[i] = SDLK_LCTRL;  break;
+	    case K_CTRLR:  keymap[i] = SDLK_RCTRL;  break;
+	    case K_ALT:    keymap[i] = SDLK_LALT;   break;
+	    case K_ALTGR:  keymap[i] = SDLK_RALT;   break;
+
+	    case K_INSERT: keymap[i] = SDLK_INSERT;   break;
+	    case K_REMOVE: keymap[i] = SDLK_DELETE;   break;
+	    case K_PGUP:   keymap[i] = SDLK_PAGEUP;   break;
+	    case K_PGDN:   keymap[i] = SDLK_PAGEDOWN; break;
+	    case K_FIND:   keymap[i] = SDLK_HOME;     break;
+	    case K_SELECT: keymap[i] = SDLK_END;      break;
+
+	    case K_NUM:  keymap[i] = SDLK_NUMLOCK;   break;
+	    case K_CAPS: keymap[i] = SDLK_CAPSLOCK;  break;
+
+	    case K_F13:   keymap[i] = SDLK_PRINT;     break;
+	    case K_HOLD:  keymap[i] = SDLK_SCROLLOCK; break;
+	    case K_PAUSE: keymap[i] = SDLK_PAUSE;     break;
+
+	    case 127: keymap[i] = SDLK_BACKSPACE; break;
+	     
+	    default: break;
+	  }
+	}
+}
+
+static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym)
+{
+	/* Set the keysym information */
+	keysym->scancode = scancode;
+	keysym->sym = keymap[scancode];
+	keysym->mod = KMOD_NONE;
+
+	/* If UNICODE is on, get the UNICODE value for the key */
+	keysym->unicode = 0;
+	if ( SDL_TranslateUNICODE ) {
+		int map;
+		SDLMod modstate;
+
+		modstate = SDL_GetModState();
+		map = 0;
+		if ( modstate & KMOD_SHIFT ) {
+			map |= (1<<KG_SHIFT);
+		}
+		if ( modstate & KMOD_CTRL ) {
+			map |= (1<<KG_CTRL);
+		}
+		if ( modstate & KMOD_ALT ) {
+			map |= (1<<KG_ALT);
+		}
+		if ( modstate & KMOD_MODE ) {
+			map |= (1<<KG_ALTGR);
+		}
+		if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) {
+			if ( modstate & KMOD_CAPS ) {
+				map ^= (1<<KG_SHIFT);
+			}
+		}
+		if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) {
+			if ( modstate & KMOD_NUM ) {
+				keysym->unicode=KVAL(vga_keymap[map][scancode]);
+			}
+		} else {
+			keysym->unicode = KVAL(vga_keymap[map][scancode]);
+		}
+	}
+	return(keysym);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsevents_c.h	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,42 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#include "SDL_gsvideo.h"
+
+/* Variables and functions exported by SDL_sysevents.c to other parts 
+   of the native video subsystem (SDL_sysvideo.c)
+*/
+extern int GS_OpenKeyboard(_THIS);
+extern void GS_CloseKeyboard(_THIS);
+extern int GS_OpenMouse(_THIS);
+extern void GS_CloseMouse(_THIS);
+extern int GS_EnterGraphicsMode(_THIS);
+extern int GS_InGraphicsMode(_THIS);
+extern void GS_LeaveGraphicsMode(_THIS);
+
+extern void GS_InitOSKeymap(_THIS);
+extern void GS_PumpEvents(_THIS);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gskeys.h	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,139 @@
+
+/* Scancodes for the Linux framebuffer console
+   - Taken with thanks from SVGAlib 1.4.0
+*/
+
+#define SCANCODE_ESCAPE			1
+
+#define SCANCODE_1			2
+#define SCANCODE_2			3
+#define SCANCODE_3			4
+#define SCANCODE_4			5
+#define SCANCODE_5			6
+#define SCANCODE_6			7
+#define SCANCODE_7			8
+#define SCANCODE_8			9
+#define SCANCODE_9			10
+#define SCANCODE_0			11
+
+#define SCANCODE_MINUS			12
+#define SCANCODE_EQUAL			13
+
+#define SCANCODE_BACKSPACE		14
+#define SCANCODE_TAB			15
+
+#define SCANCODE_Q			16
+#define SCANCODE_W			17
+#define SCANCODE_E			18
+#define SCANCODE_R			19
+#define SCANCODE_T			20
+#define SCANCODE_Y			21
+#define SCANCODE_U			22
+#define SCANCODE_I			23
+#define SCANCODE_O			24
+#define SCANCODE_P			25
+#define SCANCODE_BRACKET_LEFT		26
+#define SCANCODE_BRACKET_RIGHT		27
+
+#define SCANCODE_ENTER			28
+
+#define SCANCODE_LEFTCONTROL		29
+
+#define SCANCODE_A			30
+#define SCANCODE_S			31
+#define SCANCODE_D			32
+#define SCANCODE_F			33
+#define SCANCODE_G			34
+#define SCANCODE_H			35
+#define SCANCODE_J			36
+#define SCANCODE_K			37
+#define SCANCODE_L			38
+#define SCANCODE_SEMICOLON		39
+#define SCANCODE_APOSTROPHE		40
+#define SCANCODE_GRAVE			41
+
+#define SCANCODE_LEFTSHIFT		42
+#define SCANCODE_BACKSLASH		43
+
+#define SCANCODE_Z			44
+#define SCANCODE_X			45
+#define SCANCODE_C			46
+#define SCANCODE_V			47
+#define SCANCODE_B			48
+#define SCANCODE_N			49
+#define SCANCODE_M			50
+#define SCANCODE_COMMA			51
+#define SCANCODE_PERIOD			52
+#define SCANCODE_SLASH			53
+
+#define SCANCODE_RIGHTSHIFT		54
+#define SCANCODE_KEYPADMULTIPLY		55
+
+#define SCANCODE_LEFTALT		56
+#define SCANCODE_SPACE			57
+#define SCANCODE_CAPSLOCK		58
+
+#define SCANCODE_F1			59
+#define SCANCODE_F2			60
+#define SCANCODE_F3			61
+#define SCANCODE_F4			62
+#define SCANCODE_F5			63
+#define SCANCODE_F6			64
+#define SCANCODE_F7			65
+#define SCANCODE_F8			66
+#define SCANCODE_F9			67
+#define SCANCODE_F10			68
+
+#define SCANCODE_NUMLOCK		69
+#define SCANCODE_SCROLLLOCK		70
+
+#define SCANCODE_KEYPAD7		71
+#define SCANCODE_CURSORUPLEFT		71
+#define SCANCODE_KEYPAD8		72
+#define SCANCODE_CURSORUP		72
+#define SCANCODE_KEYPAD9		73
+#define SCANCODE_CURSORUPRIGHT		73
+#define SCANCODE_KEYPADMINUS		74
+#define SCANCODE_KEYPAD4		75
+#define SCANCODE_CURSORLEFT		75
+#define SCANCODE_KEYPAD5		76
+#define SCANCODE_KEYPAD6		77
+#define SCANCODE_CURSORRIGHT		77
+#define SCANCODE_KEYPADPLUS		78
+#define SCANCODE_KEYPAD1		79
+#define SCANCODE_CURSORDOWNLEFT		79
+#define SCANCODE_KEYPAD2		80
+#define SCANCODE_CURSORDOWN		80
+#define SCANCODE_KEYPAD3		81
+#define SCANCODE_CURSORDOWNRIGHT	81
+#define SCANCODE_KEYPAD0		82
+#define SCANCODE_KEYPADPERIOD		83
+
+#define SCANCODE_LESS			86
+
+#define SCANCODE_F11			87
+#define SCANCODE_F12			88
+
+#define SCANCODE_KEYPADENTER		96
+#define SCANCODE_RIGHTCONTROL		97
+#define SCANCODE_CONTROL		97
+#define SCANCODE_KEYPADDIVIDE		98
+#define SCANCODE_PRINTSCREEN		99
+#define SCANCODE_RIGHTALT		100
+#define SCANCODE_BREAK			101	/* Beware: is 119     */
+#define SCANCODE_BREAK_ALTERNATIVE	119	/* on some keyboards! */
+
+#define SCANCODE_HOME			102
+#define SCANCODE_CURSORBLOCKUP		103	/* Cursor key block */
+#define SCANCODE_PAGEUP			104
+#define SCANCODE_CURSORBLOCKLEFT	105	/* Cursor key block */
+#define SCANCODE_CURSORBLOCKRIGHT	106	/* Cursor key block */
+#define SCANCODE_END			107
+#define SCANCODE_CURSORBLOCKDOWN	108	/* Cursor key block */
+#define SCANCODE_PAGEDOWN		109
+#define SCANCODE_INSERT			110
+#define SCANCODE_REMOVE			111
+
+#define SCANCODE_RIGHTWIN		126
+#define SCANCODE_LEFTWIN		125
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsmouse.c	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,146 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+
+#include "SDL_error.h"
+#include "SDL_mouse.h"
+#include "SDL_events_c.h"
+#include "SDL_cursor_c.h"
+#include "SDL_gsvideo.h"
+#include "SDL_gsmouse_c.h"
+
+
+/* The implementation dependent data for the window manager cursor */
+struct WMcursor {
+	int unused;
+};
+
+/* There isn't any implementation dependent data */
+void GS_FreeWMCursor(_THIS, WMcursor *cursor)
+{
+	return;
+}
+
+/* There isn't any implementation dependent data */
+WMcursor *GS_CreateWMCursor(_THIS,
+		Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
+{
+	return((WMcursor *)0x01);
+}
+
+static void GS_MoveCursor(_THIS, SDL_Cursor *cursor, int x, int y)
+{
+	SDL_Surface *screen;
+	struct ps2_image image;
+	SDL_Rect area;
+	int mouse_y1, mouse_y2;
+	void *saved_pixels;
+	int screen_updated;
+
+	/* Lock so we don't interrupt an update with mouse motion */
+	SDL_LockCursor();
+
+	/* Make sure any pending DMA has completed */
+	if ( dma_pending ) {
+		ioctl(console_fd, PS2IOC_SENDQCT, 1);
+		dma_pending = 0;
+	}
+
+	/* Remove the cursor image from the DMA area */
+	screen = this->screen;
+	saved_pixels = screen->pixels;
+	screen->pixels = mapped_mem + screen->offset;
+	screen_updated = 0;
+	if ( cursor_drawn ) {
+		SDL_EraseCursorNoLock(this->screen);
+		cursor_drawn = 0;
+		screen_updated = 1;
+	}
+
+	/* Save the current mouse area */
+	SDL_MouseRect(&area);
+	mouse_y1 = area.y;
+	mouse_y2 = area.y+area.h;
+
+	/* Only draw the new cursor if there was one passed in */
+	if ( cursor ) {
+		/* Set the new location */
+		cursor->area.x = (x - cursor->hot_x);
+		cursor->area.y = (y - cursor->hot_y);
+
+		/* Draw the cursor at the new location */
+		if ( (SDL_cursorstate & CURSOR_VISIBLE) && screen->pixels ) {
+			SDL_DrawCursorNoLock(screen);
+			cursor_drawn = 1;
+			screen_updated = 1;
+		}
+	}
+	screen->pixels = saved_pixels;
+
+	/* Update the affected area of the screen */
+	if ( screen_updated ) {
+		SDL_MouseRect(&area);
+		if ( area.y < mouse_y1 ) {
+			mouse_y1 = area.y;
+		}
+		if ( (area.y+area.h) > mouse_y2 ) {
+			mouse_y2 = area.y+area.h;
+		}
+		image = screen_image;
+		image.y = screen->offset / screen->pitch + mouse_y1;
+		image.h = mouse_y2 - mouse_y1;
+		image.ptr = mapped_mem + image.y * screen->pitch;
+		ioctl(console_fd, PS2IOC_LOADIMAGE, &image);
+	}
+
+	/* We're finished */
+	SDL_UnlockCursor();
+}
+
+void GS_MoveWMCursor(_THIS, int x, int y)
+{
+	GS_MoveCursor(this, SDL_cursor, x, y);
+}
+
+int GS_ShowWMCursor(_THIS, WMcursor *wmcursor)
+{
+	SDL_Cursor *cursor;
+	int x, y;
+
+	/* Draw the cursor at the appropriate location */
+	SDL_GetMouseState(&x, &y);
+	if ( wmcursor ) {
+		cursor = SDL_cursor;
+	} else {
+		cursor = NULL;
+	}
+	GS_MoveCursor(this, cursor, x, y);
+	return(1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsmouse_c.h	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,43 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#include "SDL_gsvideo.h"
+
+/* This is the maximum size of the cursor sprite */
+#define CURSOR_W	32
+#define CURSOR_H	32
+#define CURSOR_W_POW	5	/* 32 = 2^5 */
+#define CURSOR_H_POW	5	/* 32 = 2^5 */
+
+/* Functions to be exported */
+extern void GS_FreeWMCursor(_THIS, WMcursor *cursor);
+extern WMcursor *GS_CreateWMCursor(_THIS,
+		Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);
+extern void GS_DrawCursor(SDL_Surface *screen);
+extern void GS_EraseCursor(SDL_Surface *screen);
+extern void GS_MoveWMCursor(_THIS, int x, int y);
+extern int GS_ShowWMCursor(_THIS, WMcursor *cursor);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsvideo.c	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,577 @@
+/*
+	SDL - Simple DirectMedia Layer
+	Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
+
+	This library is free software; you can redistribute it and/or
+	modify it under the terms of the GNU Library General Public
+	License as published by the Free Software Foundation; either
+	version 2 of the License, or (at your option) any later version.
+
+	This library 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
+	Library General Public License for more details.
+
+	You should have received a copy of the GNU Library General Public
+	License along with this library; if not, write to the Free
+	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+	Sam Lantinga
+	slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* Framebuffer console based SDL video driver implementation.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include "SDL.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_mouse.h"
+#include "SDL_sysvideo.h"
+#include "SDL_pixels_c.h"
+#include "SDL_events_c.h"
+#include "SDL_cursor_c.h"
+#include "SDL_gsvideo.h"
+#include "SDL_gsmouse_c.h"
+#include "SDL_gsevents_c.h"
+#include "SDL_gsyuv_c.h"
+
+
+/* Initialization/Query functions */
+static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat);
+static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
+static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
+static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
+static void GS_VideoQuit(_THIS);
+
+/* Hardware surface functions */
+static int GS_AllocHWSurface(_THIS, SDL_Surface *surface);
+static int GS_LockHWSurface(_THIS, SDL_Surface *surface);
+static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface);
+static void GS_FreeHWSurface(_THIS, SDL_Surface *surface);
+
+/* GS driver bootstrap functions */
+
+static int GS_Available(void)
+{
+	int console, memory;
+
+	console = open(PS2_DEV_GS, O_RDWR, 0);
+	if ( console >= 0 ) {
+		close(console);
+	}
+	memory = open(PS2_DEV_MEM, O_RDWR, 0);
+	if ( memory >= 0 ) {
+		close(memory);
+	}
+	return((console >= 0) && (memory >= 0));
+}
+
+static void GS_DeleteDevice(SDL_VideoDevice *device)
+{
+	free(device->hidden);
+	free(device);
+}
+
+static SDL_VideoDevice *GS_CreateDevice(int devindex)
+{
+	SDL_VideoDevice *this;
+
+	/* Initialize all variables that we clean on shutdown */
+	this = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
+	if ( this ) {
+		memset(this, 0, (sizeof *this));
+		this->hidden = (struct SDL_PrivateVideoData *)
+				malloc((sizeof *this->hidden));
+	}
+	if ( (this == NULL) || (this->hidden == NULL) ) {
+		SDL_OutOfMemory();
+		if ( this ) {
+			free(this);
+		}
+		return(0);
+	}
+	memset(this->hidden, 0, (sizeof *this->hidden));
+	mouse_fd = -1;
+	keyboard_fd = -1;
+
+	/* Set the function pointers */
+	this->VideoInit = GS_VideoInit;
+	this->ListModes = GS_ListModes;
+	this->SetVideoMode = GS_SetVideoMode;
+	this->CreateYUVOverlay = GS_CreateYUVOverlay;
+	this->SetColors = GS_SetColors;
+	this->UpdateRects = NULL;
+	this->VideoQuit = GS_VideoQuit;
+	this->AllocHWSurface = GS_AllocHWSurface;
+	this->CheckHWBlit = NULL;
+	this->FillHWRect = NULL;
+	this->SetHWColorKey = NULL;
+	this->SetHWAlpha = NULL;
+	this->LockHWSurface = GS_LockHWSurface;
+	this->UnlockHWSurface = GS_UnlockHWSurface;
+	this->FlipHWSurface = NULL;
+	this->FreeHWSurface = GS_FreeHWSurface;
+	this->SetIcon = NULL;
+	this->SetCaption = NULL;
+	this->GetWMInfo = NULL;
+	this->FreeWMCursor = GS_FreeWMCursor;
+	this->CreateWMCursor = GS_CreateWMCursor;
+	this->ShowWMCursor = GS_ShowWMCursor;
+	this->MoveWMCursor = GS_MoveWMCursor;
+	this->InitOSKeymap = GS_InitOSKeymap;
+	this->PumpEvents = GS_PumpEvents;
+
+	this->free = GS_DeleteDevice;
+
+	return this;
+}
+
+VideoBootStrap PS2GS_bootstrap = {
+	"ps2gs", "PlayStation 2 Graphics Synthesizer",
+	GS_Available, GS_CreateDevice
+};
+
+/* These are the pixel formats for the 32, 24, and 16 bit video modes */
+static struct {
+	int bpp;
+	Uint32 r;
+	Uint32 g;
+	Uint32 b;
+} GS_pixelmasks[] = {
+	{ 32, 0x000000FF,	/* RGB little-endian */
+	      0x0000FF00,
+	      0x00FF0000 },
+	{ 24, 0x000000FF,	/* RGB little-endian */
+	      0x0000FF00,
+	      0x00FF0000 },
+	{ 16, 0x0000001f,	/* RGB little-endian */
+	      0x000003e0,
+	      0x00007c00 },
+};
+/* This is a mapping from SDL bytes-per-pixel to GS pixel format */
+static int GS_formatmap[] = {
+	-1,		/* 0 bpp, not a legal value */
+	-1,		/* 8 bpp, not supported (yet?) */
+	PS2_GS_PSMCT16,	/* 16 bpp */
+	PS2_GS_PSMCT24,	/* 24 bpp */
+	PS2_GS_PSMCT32	/* 32 bpp */
+};
+
+static unsigned long long head_tags[] __attribute__((aligned(16))) = {
+	4 | (1LL << 60),	/* GIFtag */
+	0x0e,			/* A+D */
+	0,			/* 2 */
+	PS2_GS_BITBLTBUF,
+	0,			/* 4 */
+	PS2_GS_TRXPOS,
+	0,			/* 6 */
+	PS2_GS_TRXREG,
+	0,			/* 8 */
+	PS2_GS_TRXDIR
+};
+
+#define MAXIMG		(32767 * 16)
+#define MAXTAGS		8
+
+static inline int loadimage_nonblock(int fd, struct ps2_image *image, int size,
+                                     unsigned long long *hm,
+                                     unsigned long long *im)
+{
+	struct ps2_plist plist;
+	struct ps2_packet packet[1 + MAXTAGS * 2];
+	int isize;
+	int pnum, it, eop;
+	char *data;
+
+	/* initialize the variables */
+	data = (char *)image->ptr;
+	pnum = it = eop = 0;
+	plist.packet = packet;
+
+	/* make BITBLT packet */
+	packet[pnum].ptr = hm;
+	packet[pnum].len = sizeof(head_tags);
+	pnum++;
+	hm[2] = ((unsigned long long)image->fbp << 32) |
+	        ((unsigned long long)image->fbw << 48) |
+	        ((unsigned long long)image->psm << 56);
+	hm[4] = ((unsigned long long)image->x << 32) |
+	        ((unsigned long long)image->y << 48);
+	hm[6] = (unsigned long long)image->w |
+	        ((unsigned long long)image->h << 32);
+
+	/* make image mode tags */
+	while (!eop) {
+		isize = size > MAXIMG ? MAXIMG : size;
+		size -= isize;
+		eop = (size == 0);
+
+		packet[pnum].ptr = &im[it];
+		packet[pnum].len = sizeof(unsigned long long) * 2;
+		pnum++;
+		im[it++] = (isize >> 4) | (eop ? (1 << 15) : 0) | (2LL << 58);
+		im[it++] = 0;
+
+		packet[pnum].ptr = (void *)data;
+		packet[pnum].len = isize;
+		pnum++;
+		data += isize;
+	}
+	plist.num = pnum;
+
+	return ioctl(fd, PS2IOC_SENDL, &plist);
+}
+
+static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
+{
+	struct ps2_screeninfo vinfo;
+
+	/* Initialize the library */
+	console_fd = open(PS2_DEV_GS, O_RDWR, 0);
+	if ( console_fd < 0 ) {
+		SDL_SetError("Unable to open %s", PS2_DEV_GS);
+		return(-1);
+	}
+	memory_fd = open(PS2_DEV_MEM, O_RDWR, 0);
+	if ( memory_fd < 0 ) {
+		close(console_fd);
+		console_fd = -1;
+		SDL_SetError("Unable to open %s", PS2_DEV_MEM);
+		return(-1);
+	}
+
+	/* Determine the current screen depth */
+	if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) {
+		close(memory_fd);
+		close(console_fd);
+		console_fd = -1;
+		SDL_SetError("Couldn't get console pixel format");
+		return(-1);
+	}
+	if ( vinfo.mode != PS2_GS_VESA ) {
+		GS_VideoQuit(this);
+		SDL_SetError("Console must be in VESA video mode");
+		return(-1);
+	}
+	switch (vinfo.psm) {
+	    /* Supported pixel formats */
+	    case PS2_GS_PSMCT32:
+	    case PS2_GS_PSMCT24:
+	    case PS2_GS_PSMCT16:
+		break;
+	    default:
+		GS_VideoQuit(this);
+		SDL_SetError("Unknown console pixel format: %d", vinfo.psm);
+		return(-1);
+	}
+	vformat->BitsPerPixel = GS_pixelmasks[vinfo.psm].bpp;
+	vformat->Rmask = GS_pixelmasks[vinfo.psm].r;
+	vformat->Gmask = GS_pixelmasks[vinfo.psm].g;
+	vformat->Bmask = GS_pixelmasks[vinfo.psm].b;
+	saved_vinfo = vinfo;
+
+	/* Enable mouse and keyboard support */
+	if ( GS_OpenKeyboard(this) < 0 ) {
+		GS_VideoQuit(this);
+		SDL_SetError("Unable to open keyboard");
+		return(-1);
+	}
+	if ( GS_OpenMouse(this) < 0 ) {
+		const char *sdl_nomouse;
+
+		sdl_nomouse = getenv("SDL_NOMOUSE");
+		if ( ! sdl_nomouse ) {
+			GS_VideoQuit(this);
+			SDL_SetError("Unable to open mouse");
+			return(-1);
+		}
+	}
+
+	/* We're done! */
+	return(0);
+}
+
+static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
+{
+	static SDL_Rect GS_mode_list[] = {
+		{ 0, 0, 1280, 1024 },
+		{ 0, 0, 1024, 768 },
+		{ 0, 0, 800, 600 },
+		{ 0, 0, 640, 480 }
+	};
+	static SDL_Rect *GS_modes[] = {
+		&GS_mode_list[0],
+		&GS_mode_list[1],
+		&GS_mode_list[2],
+		&GS_mode_list[3],
+		NULL
+	};
+	SDL_Rect **modes;
+
+	switch (format->BitsPerPixel) {
+	    case 16:
+	    case 24:
+	    case 32:
+		modes = GS_modes;
+		break;
+	    default:
+		modes = NULL;
+		break;
+	}
+	return(modes);
+}
+
+/* Various screen update functions available */
+static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects);
+
+static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
+				int width, int height, int bpp, Uint32 flags)
+{
+	struct ps2_screeninfo vinfo;
+
+	/* Set the terminal into graphics mode */
+	if ( GS_EnterGraphicsMode(this) < 0 ) {
+		return(NULL);
+	}
+
+	/* Set the video mode and get the final screen format */
+	if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) {
+		SDL_SetError("Couldn't get console screen info");
+		return(NULL);
+	}
+	if ( (vinfo.w != width) || (vinfo.h != height) ||
+	     (GS_pixelmasks[vinfo.psm].bpp != bpp) ) {
+		switch (width) {
+		    case 640:
+			vinfo.res = PS2_GS_640x480;
+			break;
+		    case 800:
+			vinfo.res = PS2_GS_800x600;
+			break;
+		    case 1024:
+			vinfo.res = PS2_GS_1024x768;
+			break;
+		    case 1280:
+			vinfo.res = PS2_GS_1280x1024;
+			break;
+		    default:
+			SDL_SetError("Unsupported resolution: %dx%d\n",
+			             width, height);
+			return(NULL);
+		}
+		vinfo.res |= (PS2_GS_75Hz << 8);
+		vinfo.w = width;
+		vinfo.h = height;
+		vinfo.fbp = 0;
+		vinfo.psm = GS_formatmap[bpp/8];
+		if ( vinfo.psm < 0 ) {
+			SDL_SetError("Unsupported depth: %d bpp\n", bpp);
+			return(NULL);
+		}
+		if ( ioctl(console_fd, PS2IOC_SSCREENINFO, &vinfo) < 0 ) {
+			SDL_SetError("Couldn't set console screen info");
+			return(NULL);
+		}
+
+		/* Unmap the previous DMA buffer */
+		if ( mapped_mem ) {
+			munmap(mapped_mem, mapped_len);
+			mapped_mem = NULL;
+		}
+	}
+	if ( ! SDL_ReallocFormat(current, GS_pixelmasks[vinfo.psm].bpp,
+	                                  GS_pixelmasks[vinfo.psm].r,
+	                                  GS_pixelmasks[vinfo.psm].g,
+	                                  GS_pixelmasks[vinfo.psm].b, 0) ) {
+		return(NULL);
+	}
+
+	/* Set up the new mode framebuffer */
+	current->flags = SDL_FULLSCREEN;
+	current->w = vinfo.w;
+	current->h = vinfo.h;
+	current->pitch = SDL_CalculatePitch(current);
+
+	/* Memory map the DMA area for block memory transfer */
+	if ( ! mapped_mem ) {
+		pixels_len = height * current->pitch;
+		mapped_len = pixels_len +
+		             /* Screen update DMA command area */
+		             sizeof(head_tags) + ((2 * MAXTAGS) * 16);
+		mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE,
+		                  MAP_SHARED, memory_fd, 0);
+		if ( mapped_mem == MAP_FAILED ) {
+			SDL_SetError("Unable to map %d bytes for DMA",
+			             mapped_len);
+			mapped_mem = NULL;
+			return(NULL);
+		}
+
+		/* Set up the entire screen for DMA transfer */
+		screen_image.ptr = mapped_mem;
+		screen_image.fbp = 0;
+		screen_image.fbw = (vinfo.w + 63) / 64;
+		screen_image.psm = vinfo.psm;
+		screen_image.x = 0;
+		screen_image.y = 0;
+		screen_image.w = vinfo.w;
+		screen_image.h = vinfo.h;
+
+		/* get screen image data size (qword aligned) */
+		screen_image_size = (vinfo.w * vinfo.h);
+		switch (screen_image.psm) {
+		    case PS2_GS_PSMCT32:
+			screen_image_size *= 4;
+			break;
+		    case PS2_GS_PSMCT24:
+			screen_image_size *= 3;
+			break;
+		    case PS2_GS_PSMCT16:
+			screen_image_size *= 2;
+			break;
+		}
+		screen_image_size = (screen_image_size + 15) & ~15;
+
+		/* Set up the memory for screen update DMA commands */
+		head_tags_mem = (unsigned long long *)
+		                (mapped_mem + pixels_len);
+		image_tags_mem = (unsigned long long *)
+		                 ((caddr_t)head_tags_mem + sizeof(head_tags));
+		memcpy(head_tags_mem, head_tags, sizeof(head_tags));
+	}
+	current->pixels = NULL;
+	if ( getenv("SDL_FULLSCREEN_UPDATE") ) {
+		/* Correct semantics */
+		current->flags |= SDL_ASYNCBLIT;
+	} else {
+		/* We lie here - the screen memory isn't really the visible
+		   display memory and still requires an update, but this
+		   has the desired effect for most applications.
+		 */
+		current->flags |= SDL_HWSURFACE;
+	}
+
+	/* Set the update rectangle function */
+	this->UpdateRects = GS_DMAFullUpdate;
+
+	/* We're done */
+	return(current);
+}
+
+/* We don't support hardware surfaces yet */
+static int GS_AllocHWSurface(_THIS, SDL_Surface *surface)
+{
+	return(-1);
+}
+static void GS_FreeHWSurface(_THIS, SDL_Surface *surface)
+{
+	return;
+}
+static int GS_LockHWSurface(_THIS, SDL_Surface *surface)
+{
+	if ( surface == this->screen ) {
+		/* Since mouse motion affects 'pixels', lock it */
+		SDL_LockCursor();
+
+		/* Make sure any pending DMA has completed */
+		if ( dma_pending ) {
+			ioctl(console_fd, PS2IOC_SENDQCT, 1);
+			dma_pending = 0;
+		}
+
+		/* If the cursor is drawn on the DMA area, remove it */
+		if ( cursor_drawn ) {
+			surface->pixels = mapped_mem + surface->offset;
+			SDL_EraseCursorNoLock(this->screen);
+			cursor_drawn = 0;
+		}
+
+		/* Set the surface pixels to the base of the DMA area */
+		surface->pixels = mapped_mem;
+
+		/* We're finished! */
+		SDL_UnlockCursor();
+	}
+	return(0);
+}
+static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface)
+{
+	if ( surface == this->screen ) {
+		/* Since mouse motion affects 'pixels', lock it */
+		SDL_LockCursor();
+		surface->pixels = NULL;
+		SDL_UnlockCursor();
+	}
+}
+
+static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects)
+{
+	/* Lock so we aren't interrupted by a mouse update */
+	SDL_LockCursor();
+
+	/* Make sure any pending DMA has completed */
+	if ( dma_pending ) {
+		ioctl(console_fd, PS2IOC_SENDQCT, 1);
+		dma_pending = 0;
+	}
+
+	/* If the mouse is visible, draw it on the DMA area */
+	if ( (SDL_cursorstate & CURSOR_VISIBLE) && !cursor_drawn ) {
+		this->screen->pixels = mapped_mem + this->screen->offset;
+		SDL_DrawCursorNoLock(this->screen);
+		this->screen->pixels = NULL;
+		cursor_drawn = 1;
+	}
+
+	/* Put the image onto the screen */
+	loadimage_nonblock(console_fd,
+	                   &screen_image, screen_image_size,
+	                   head_tags_mem, image_tags_mem);
+	dma_pending = 1;
+
+	/* We're finished! */
+	SDL_UnlockCursor();
+}
+
+static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
+{
+	return(0);
+}
+
+static void GS_VideoQuit(_THIS)
+{
+	/* Close console and input file descriptors */
+	if ( console_fd > 0 ) {
+		/* Unmap the video framebuffer */
+		if ( mapped_mem ) {
+			/* Unmap the video framebuffer */
+			munmap(mapped_mem, mapped_len);
+			mapped_mem = NULL;
+		}
+		close(memory_fd);
+
+		/* Restore the original video mode */
+		if ( GS_InGraphicsMode(this) ) {
+			ioctl(console_fd, PS2IOC_SSCREENINFO, &saved_vinfo);
+		}
+
+		/* We're all done with the graphics device */
+		close(console_fd);
+		console_fd = -1;
+	}
+	GS_CloseMouse(this);
+	GS_CloseKeyboard(this);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsvideo.h	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,92 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#ifndef _SDL_gsvideo_h
+#define _SDL_gsvideo_h
+
+#include <sys/types.h>
+#include <termios.h>
+#include <linux/ps2/dev.h>
+#include <linux/ps2/gs.h>
+
+#include "SDL_mouse.h"
+#include "SDL_mutex.h"
+#include "SDL_sysvideo.h"
+
+/* Hidden "this" pointer for the video functions */
+#define _THIS	SDL_VideoDevice *this
+
+
+/* Private display data */
+struct SDL_PrivateVideoData {
+	/* Gotta love that simple PS2 graphics interface. :) */
+	int console_fd;
+	int memory_fd;
+	struct ps2_screeninfo saved_vinfo;
+
+	/* Ye olde linux keyboard code */
+	int current_vt;
+	int saved_vt;
+	int keyboard_fd;
+	int saved_kbd_mode;
+	struct termios saved_kbd_termios;
+
+	/* Ye olde linux mouse code */
+	int mouse_fd;
+	int cursor_drawn;
+
+	/* The memory mapped DMA area and associated variables */
+	caddr_t mapped_mem;
+	int pixels_len;
+	int mapped_len;
+	struct ps2_image screen_image;
+	int screen_image_size;
+	unsigned long long *head_tags_mem;
+	unsigned long long *image_tags_mem;
+	int dma_pending;
+};
+/* Old variable names */
+#define console_fd		(this->hidden->console_fd)
+#define memory_fd		(this->hidden->memory_fd)
+#define saved_vinfo		(this->hidden->saved_vinfo)
+#define current_vt		(this->hidden->current_vt)
+#define saved_vt		(this->hidden->saved_vt)
+#define keyboard_fd		(this->hidden->keyboard_fd)
+#define saved_kbd_mode		(this->hidden->saved_kbd_mode)
+#define saved_kbd_termios	(this->hidden->saved_kbd_termios)
+#define mouse_fd		(this->hidden->mouse_fd)
+#define cursor_drawn		(this->hidden->cursor_drawn)
+#define mapped_mem		(this->hidden->mapped_mem)
+#define pixels_len		(this->hidden->pixels_len)
+#define mapped_len		(this->hidden->mapped_len)
+#define screen_image		(this->hidden->screen_image)
+#define screen_image_size	(this->hidden->screen_image_size)
+#define head_tags_mem		(this->hidden->head_tags_mem)
+#define image_tags_mem		(this->hidden->image_tags_mem)
+#define dma_pending		(this->hidden->dma_pending)
+
+#endif /* _SDL_gsvideo_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsyuv.c	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,467 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* This is the Playstation 2 implementation of YUV video overlays */
+
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <asm/page.h>		/* For definition of PAGE_SIZE */
+
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_gsyuv_c.h"
+#include "SDL_yuvfuncs.h"
+
+/* The maximum number of 16x16 pixel block converted at once */
+#define MAX_MACROBLOCKS	1024	/* 2^10 macroblocks at once */
+
+/* The functions used to manipulate video overlays */
+static struct private_yuvhwfuncs gs_yuvfuncs = {
+	GS_LockYUVOverlay,
+	GS_UnlockYUVOverlay,
+	GS_DisplayYUVOverlay,
+	GS_FreeYUVOverlay
+};
+
+struct private_yuvhwdata {
+	int ipu_fd;
+	Uint8 *pixels;
+	int macroblocks;
+	int dma_len;
+	caddr_t dma_mem;
+	caddr_t ipu_imem;
+	caddr_t ipu_omem;
+	caddr_t dma_tags;
+	unsigned long long *stretch_x1y1;
+	unsigned long long *stretch_x2y2;
+	struct ps2_plist plist;
+
+	/* These are just so we don't have to allocate them separately */
+	Uint16 pitches[3];
+	Uint8 *planes[3];
+};
+
+static int power_of_2(int value)
+{
+	int shift;
+
+	for ( shift = 0; (1<<shift) < value; ++shift ) {
+		/* Keep looking */ ;
+	}
+	return(shift);
+}
+
+SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
+{
+	SDL_Overlay *overlay;
+	struct private_yuvhwdata *hwdata;
+	int map_offset;
+	unsigned long long *tags;
+	caddr_t base;
+	int bpp;
+	int fbp, fbw, psm;
+	int x, y, w, h;
+	int pnum;
+	struct ps2_packet *packet;
+	struct ps2_packet tex_packet;
+
+	/* We can only decode blocks of 16x16 pixels */
+	if ( (width & 15) || (height & 15) ) {
+		SDL_SetError("Overlay width/height must be multiples of 16");
+		return(NULL);
+	}
+	/* Make sure the image isn't too large for a single DMA transfer */
+	if ( ((width/16) * (height/16)) > MAX_MACROBLOCKS ) {
+		SDL_SetError("Overlay too large (maximum size: %d pixels)",
+		             MAX_MACROBLOCKS * 16 * 16);
+		return(NULL);
+	}
+
+	/* Double-check the requested format.  For simplicity, we'll only
+	   support planar YUV formats.
+	 */
+	switch (format) {
+	    case SDL_YV12_OVERLAY:
+	    case SDL_IYUV_OVERLAY:
+		/* Supported planar YUV format */
+		break;
+	    default:
+		SDL_SetError("Unsupported YUV format");
+		return(NULL);
+	}
+
+	/* Create the overlay structure */
+	overlay = (SDL_Overlay *)malloc(sizeof *overlay);
+	if ( overlay == NULL ) {
+		SDL_OutOfMemory();
+		return(NULL);
+	}
+	memset(overlay, 0, (sizeof *overlay));
+
+	/* Fill in the basic members */
+	overlay->format = format;
+	overlay->w = width;
+	overlay->h = height;
+
+	/* Set up the YUV surface function structure */
+	overlay->hwfuncs = &gs_yuvfuncs;
+	overlay->hw_overlay = 1;
+
+	/* Create the pixel data */
+	hwdata = (struct private_yuvhwdata *)malloc(sizeof *hwdata);
+	overlay->hwdata = hwdata;
+	if ( hwdata == NULL ) {
+		SDL_FreeYUVOverlay(overlay);
+		SDL_OutOfMemory();
+		return(NULL);
+	}
+	hwdata->ipu_fd = -1;
+	hwdata->pixels = (Uint8 *)malloc(width*height*2);
+	if ( hwdata->pixels == NULL ) {
+		SDL_FreeYUVOverlay(overlay);
+		SDL_OutOfMemory();
+		return(NULL);
+	}
+	hwdata->macroblocks = (width/16) * (height/16);
+
+	/* Find the pitch and offset values for the overlay */
+	overlay->pitches = hwdata->pitches;
+	overlay->pixels = hwdata->planes;
+	switch (format) {
+	    case SDL_YV12_OVERLAY:
+	    case SDL_IYUV_OVERLAY:
+		overlay->pitches[0] = overlay->w;
+		overlay->pitches[1] = overlay->pitches[0] / 2;
+		overlay->pitches[2] = overlay->pitches[0] / 2;
+	        overlay->pixels[0] = hwdata->pixels;
+	        overlay->pixels[1] = overlay->pixels[0] +
+		                     overlay->pitches[0] * overlay->h;
+	        overlay->pixels[2] = overlay->pixels[1] +
+		                     overlay->pitches[1] * overlay->h / 2;
+		overlay->planes = 3;
+		break;
+	    default:
+		/* We should never get here (caught above) */
+		break;
+	}
+
+	/* Theoretically we could support several concurrent decode
+	   streams queueing up on the same file descriptor, but for
+	   simplicity we'll support only one.  Opening the IPU more
+	   than once will fail with EBUSY.
+	*/
+	hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR);
+	if ( hwdata->ipu_fd < 0 ) {
+		SDL_FreeYUVOverlay(overlay);
+		SDL_SetError("Playstation 2 IPU busy");
+		return(NULL);
+	}
+
+	/* Allocate a DMA area for pixel conversion */
+	bpp = this->screen->format->BytesPerPixel;
+	map_offset = (mapped_len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+	hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) +
+	                  width * height * bpp +
+	                  hwdata->macroblocks * (16 * sizeof(long long)) +
+	                  12 * sizeof(long long);
+	hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ|PROT_WRITE,
+	                       MAP_SHARED, memory_fd, map_offset);
+	if ( hwdata->dma_mem == MAP_FAILED ) {
+		hwdata->ipu_imem = (caddr_t)0;
+		SDL_FreeYUVOverlay(overlay);
+		SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len);
+		return(NULL);
+	}
+	hwdata->ipu_imem = hwdata->dma_mem;
+	hwdata->ipu_omem = hwdata->ipu_imem +
+	                   hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
+	hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp;
+
+	/* Allocate memory for the DMA packets */
+	hwdata->plist.num = hwdata->macroblocks * 4 + 1;
+	hwdata->plist.packet = (struct ps2_packet *)malloc(
+	                       hwdata->plist.num*sizeof(struct ps2_packet));
+	if ( ! hwdata->plist.packet ) {
+		SDL_FreeYUVOverlay(overlay);
+		SDL_OutOfMemory();
+		return(NULL);
+	}
+	pnum = 0;
+	packet = hwdata->plist.packet;
+
+	/* Set up the tags to send the image to the screen */
+	tags = (unsigned long long *)hwdata->dma_tags;
+	base = hwdata->ipu_omem;
+	fbp = screen_image.fbp;
+	fbw = screen_image.fbw;
+	psm = screen_image.psm;
+	y = screen_image.h;	/* Offscreen video memory */
+	for ( h=height/16; h; --h ) {
+		x = 0;			/* Visible video memory */
+		for ( w=width/16; w; --w ) {
+			/* The head tag */
+			packet[pnum].ptr = &tags[0];
+			packet[pnum].len = 10 * sizeof(*tags);
+			++pnum;
+			tags[0] = 4 | (1LL << 60);	/* GIFtag */
+			tags[1] = 0x0e;			/* A+D */
+			tags[2] = ((unsigned long long)fbp << 32) |
+			          ((unsigned long long)fbw << 48) |
+			          ((unsigned long long)psm << 56);
+			tags[3] = PS2_GS_BITBLTBUF;
+			tags[4] = ((unsigned long long)x << 32) |
+			          ((unsigned long long)y << 48);
+			tags[5] = PS2_GS_TRXPOS;
+			tags[6] = (unsigned long long)16 |
+			          ((unsigned long long)16 << 32);
+			tags[7] = PS2_GS_TRXREG;
+			tags[8] = 0;
+			tags[9] = PS2_GS_TRXDIR;
+			/* Now the actual image data */
+			packet[pnum].ptr = &tags[10];
+			packet[pnum].len = 2 * sizeof(*tags);
+			++pnum;
+			tags[10] = ((16*16*bpp) >> 4) | (2LL << 58);
+			tags[11] = 0;
+			packet[pnum].ptr = (void *)base;
+			packet[pnum].len = 16 * 16 * bpp;
+			++pnum;
+			packet[pnum].ptr = &tags[12];
+			packet[pnum].len = 2 * sizeof(*tags);
+			++pnum;
+			tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58);
+			tags[13] = 0;
+
+			tags += 16;
+			base += 16 * 16 * bpp;
+
+			x += 16;
+		}
+		y += 16;
+	}
+
+	/* Set up the texture memory area for the video */
+	tex_packet.ptr = tags;
+	tex_packet.len = 8 * sizeof(*tags);
+	tags[0] = 3 | (1LL << 60);	/* GIFtag */
+	tags[1] = 0x0e;			/* A+D */
+	tags[2] = (screen_image.h * screen_image.w) / 64 +
+	          ((unsigned long long)fbw << 14) +
+	          ((unsigned long long)psm << 20) +
+	          ((unsigned long long)power_of_2(width) << 26) +
+	          ((unsigned long long)power_of_2(height) << 30) +
+	          ((unsigned long long)1 << 34) +
+	          ((unsigned long long)1 << 35);
+	tags[3] = PS2_GS_TEX0_1;
+	tags[4] = (1 << 5) + (1 << 6);
+	tags[5] = PS2_GS_TEX1_1;
+	tags[6] = 0;
+	tags[7] = PS2_GS_TEXFLUSH;
+	ioctl(console_fd, PS2IOC_SEND, &tex_packet);
+
+	/* Set up the tags for scaling the image */
+	packet[pnum].ptr = tags;
+	packet[pnum].len = 12 * sizeof(*tags);
+	++pnum;
+	tags[0] = 5 | (1LL << 60);	/* GIFtag */
+	tags[1] = 0x0e;			/* A+D */
+	tags[2] = 6 + (1 << 4) + (1 << 8);
+	tags[3] = PS2_GS_PRIM;
+	tags[4] = ((unsigned long long)0 * 16) +
+	           (((unsigned long long)0 * 16) << 16);
+	tags[5] = PS2_GS_UV;
+	tags[6] = 0; /* X1, Y1 */
+	tags[7] = PS2_GS_XYZ2;
+	hwdata->stretch_x1y1 = &tags[6];
+	tags[8] = ((unsigned long long)overlay->w * 16) +
+	           (((unsigned long long)overlay->h * 16) << 16);
+	tags[9] = PS2_GS_UV;
+	tags[10] = 0; /* X2, Y2 */
+	tags[11] = PS2_GS_XYZ2;
+	hwdata->stretch_x2y2 = &tags[10];
+
+	/* We're all done.. */
+	return(overlay);
+}
+
+int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay)
+{
+	return(0);
+}
+
+void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay)
+{
+	return;
+}
+
+int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
+{
+	struct private_yuvhwdata *hwdata;
+	__u32 cmd;
+	struct ps2_packet packet;
+	int h, w, i;
+	Uint32 *lum, *Cr, *Cb;
+	int lum_pitch;
+	int crb_pitch;
+	Uint32 *lum_src, *Cr_src, *Cb_src;
+	Uint32 *src, *dst;
+	unsigned int x, y;
+	SDL_Surface *screen;
+
+	/* Find out where the various portions of the image are */
+	hwdata = overlay->hwdata;
+	switch (overlay->format) {
+	    case SDL_YV12_OVERLAY:
+		lum = (Uint32 *)overlay->pixels[0];
+		Cr =  (Uint32 *)overlay->pixels[1];
+		Cb =  (Uint32 *)overlay->pixels[2];
+		break;
+	    case SDL_IYUV_OVERLAY:
+		lum = (Uint32 *)overlay->pixels[0];
+		Cr =  (Uint32 *)overlay->pixels[2];
+		Cb =  (Uint32 *)overlay->pixels[1];
+	    default:
+		SDL_SetError("Unsupported YUV format in blit (??)");
+		return(-1);
+	}
+	dst = (Uint32 *)hwdata->ipu_imem;
+	lum_pitch = overlay->w/4;
+	crb_pitch = (overlay->w/2)/4;
+
+	/* Copy blocks of 16x16 pixels to the DMA area */
+	for ( h=overlay->h/16; h; --h ) {
+		lum_src = lum;
+		Cr_src = Cr;
+		Cb_src = Cb;
+		for ( w=overlay->w/16; w; --w ) {
+			src = lum_src;
+			for ( i=0; i<16; ++i ) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+				dst[3] = src[3];
+				src += lum_pitch;
+				dst += 4;
+			}
+			src = Cb_src;
+			for ( i=0; i<8; ++i ) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				src += crb_pitch;
+				dst += 2;
+			}
+			src = Cr_src;
+			for ( i=0; i<8; ++i ) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				src += crb_pitch;
+				dst += 2;
+			}
+			lum_src += 16 / 4;
+			Cb_src += 8 / 4;
+			Cr_src += 8 / 4;
+		}
+		lum += lum_pitch * 16;
+		Cr += crb_pitch * 8;
+		Cb += crb_pitch * 8;
+	}
+
+	/* Send the macroblock data to the IPU */
+#ifdef DEBUG_YUV
+	fprintf(stderr, "Sending data to IPU..\n");
+#endif
+	packet.ptr = hwdata->ipu_imem;
+	packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
+	ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet);
+
+	/* Trigger the DMA to the IPU for conversion */
+#ifdef DEBUG_YUV
+	fprintf(stderr, "Trigging conversion command\n");
+#endif
+	cmd = (7 << 28) + hwdata->macroblocks;
+	if ( screen_image.psm == PS2_GS_PSMCT16 ) {
+		cmd += (1 << 27) +	/* Output RGB 555 */
+		       (1 << 26);	/* Dither output */
+	}
+	ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd);
+
+	/* Retrieve the converted image from the IPU */
+#ifdef DEBUG_YUV
+	fprintf(stderr, "Retrieving data from IPU..\n");
+#endif
+	packet.ptr = hwdata->ipu_omem;
+	packet.len = overlay->w * overlay->h *
+	             this->screen->format->BytesPerPixel;
+	ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet);
+
+#ifdef DEBUG_YUV
+	fprintf(stderr, "Copying image to screen..\n");
+#endif
+	/* Wait for previous DMA to complete */
+	ioctl(console_fd, PS2IOC_SENDQCT, 1);
+
+	/* Send the current image to the screen and scale it */
+	screen = this->screen;
+	x = (unsigned int)dstrect->x;
+	y = (unsigned int)dstrect->y;
+	if ( screen->offset ) {
+		x += (screen->offset % screen->pitch) /
+		     screen->format->BytesPerPixel;
+		y += (screen->offset / screen->pitch);
+	}
+	*hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
+	x += (unsigned int)dstrect->w;
+	y += (unsigned int)dstrect->h;
+	*hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16);
+	return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist);
+}
+
+void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
+{
+	struct private_yuvhwdata *hwdata;
+
+	hwdata = overlay->hwdata;
+	if ( hwdata ) {
+		if ( hwdata->ipu_fd >= 0 ) {
+			close(hwdata->ipu_fd);
+		}
+		if ( hwdata->dma_mem ) {
+			munmap(hwdata->dma_mem, hwdata->dma_len);
+		}
+		if ( hwdata->plist.packet ) {
+			free(hwdata->plist.packet);
+		}
+		if ( hwdata->pixels ) {
+			free(hwdata->pixels);
+		}
+		free(hwdata);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps2gs/SDL_gsyuv_c.h	Sat Jun 16 03:17:45 2001 +0000
@@ -0,0 +1,41 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* This is the Playstation 2 implementation of YUV video overlays */
+
+#include "SDL_video.h"
+#include "SDL_gsvideo.h"
+
+extern SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display);
+
+extern int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay);
+
+extern void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay);
+
+extern int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect);
+
+extern void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay);