Added Linux PlayStation 2 Graphics Synthesizer support
authorSam Lantinga <slouken@lokigames.com>
Sat, 16 Jun 2001 03:17:45 +0000
changeset 70f590dd383b5d
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
     1.1 --- a/configure.in	Sat Jun 16 02:48:39 2001 +0000
     1.2 +++ b/configure.in	Sat Jun 16 03:17:45 2001 +0000
     1.3 @@ -666,6 +666,32 @@
     1.4      fi
     1.5  }
     1.6  
     1.7 +dnl See if we're running on PlayStation 2 hardware
     1.8 +CheckPS2GS()
     1.9 +{
    1.10 +dnl    AC_ARG_ENABLE(video-ps2gs,
    1.11 +dnl[  --enable-video-ps2gs    use PlayStation 2 GS video driver [default=yes]],
    1.12 +dnl                  , enable_video_ps2gs=yes)
    1.13 +enable_video_ps2gs=yes
    1.14 +    if test x$enable_video = xyes -a x$enable_video_ps2gs = xyes; then
    1.15 +        dnl AC_MSG_CHECKING(for PlayStation 2 GS support)
    1.16 +        video_ps2gs=no
    1.17 +        AC_TRY_COMPILE([
    1.18 +         #include <linux/ps2/dev.h>
    1.19 +         #include <linux/ps2/gs.h>
    1.20 +        ],[
    1.21 +        ],[
    1.22 +        video_ps2gs=yes
    1.23 +        ])
    1.24 +        dnl AC_MSG_RESULT($video_ps2gs)
    1.25 +        if test x$video_ps2gs = xyes; then
    1.26 +            CFLAGS="$CFLAGS -DENABLE_PS2GS"
    1.27 +            VIDEO_SUBDIRS="$VIDEO_SUBDIRS ps2gs"
    1.28 +            VIDEO_DRIVERS="$VIDEO_DRIVERS ps2gs/libvideo_ps2gs.la"
    1.29 +        fi
    1.30 +    fi
    1.31 +}
    1.32 +
    1.33  dnl Find the GGI includes
    1.34  CheckGGI()
    1.35  {
    1.36 @@ -1111,6 +1137,7 @@
    1.37          CheckNANOX
    1.38          CheckDGA
    1.39          CheckFBCON
    1.40 +        CheckPS2GS
    1.41          CheckGGI
    1.42          CheckSVGA
    1.43          CheckAAlib
    1.44 @@ -2011,6 +2038,7 @@
    1.45  src/video/dga/Makefile
    1.46  src/video/nanox/Makefile
    1.47  src/video/fbcon/Makefile
    1.48 +src/video/ps2gs/Makefile
    1.49  src/video/ggi/Makefile
    1.50  src/video/maccommon/Makefile
    1.51  src/video/macdsp/Makefile
     2.1 --- a/docs.html	Sat Jun 16 02:48:39 2001 +0000
     2.2 +++ b/docs.html	Sat Jun 16 03:17:45 2001 +0000
     2.3 @@ -16,6 +16,7 @@
     2.4  Major changes since SDL 1.0.0:
     2.5  </H2>
     2.6  <UL>
     2.7 +	<LI> 1.2.1: Added Linux PlayStation 2 Graphics Synthesizer support
     2.8  	<LI> 1.2.1: Added an audio driver that writes to disk (thanks Ryan!)
     2.9  	<LI> 1.2.1: Mouse wheel sends mouse button (4/5) events on Windows
    2.10  	<LI> 1.2.1: Added MacOS X Project Builder projects (thanks Darrell!)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/video/ps2gs/.cvsignore	Sat Jun 16 03:17:45 2001 +0000
     3.3 @@ -0,0 +1,6 @@
     3.4 +Makefile.in
     3.5 +Makefile
     3.6 +.libs
     3.7 +*.o
     3.8 +*.lo
     3.9 +*.la
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/video/ps2gs/Makefile.am	Sat Jun 16 03:17:45 2001 +0000
     4.3 @@ -0,0 +1,17 @@
     4.4 +
     4.5 +## Makefile.am for SDL using the framebuffer console video driver
     4.6 +
     4.7 +noinst_LTLIBRARIES = libvideo_ps2gs.la
     4.8 +libvideo_ps2gs_la_SOURCES = $(PS2GS_SRCS)
     4.9 +
    4.10 +# The SDL framebuffer console video driver sources
    4.11 +PS2GS_SRCS = 			\
    4.12 +	SDL_gsevents.c		\
    4.13 +	SDL_gsevents_c.h	\
    4.14 +	SDL_gskeys.h		\
    4.15 +	SDL_gsmouse.c		\
    4.16 +	SDL_gsmouse_c.h		\
    4.17 +	SDL_gsvideo.c		\
    4.18 +	SDL_gsvideo.h		\
    4.19 +	SDL_gsyuv.c		\
    4.20 +	SDL_gsyuv_c.h
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/video/ps2gs/SDL_gsevents.c	Sat Jun 16 03:17:45 2001 +0000
     5.3 @@ -0,0 +1,983 @@
     5.4 +/*
     5.5 +	SDL - Simple DirectMedia Layer
     5.6 +	Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     5.7 +
     5.8 +	This library is free software; you can redistribute it and/or
     5.9 +	modify it under the terms of the GNU Library General Public
    5.10 +	License as published by the Free Software Foundation; either
    5.11 +	version 2 of the License, or (at your option) any later version.
    5.12 +
    5.13 +	This library is distributed in the hope that it will be useful,
    5.14 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.15 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    5.16 +	Library General Public License for more details.
    5.17 +
    5.18 +	You should have received a copy of the GNU Library General Public
    5.19 +	License along with this library; if not, write to the Free
    5.20 +	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.21 +
    5.22 +	Sam Lantinga
    5.23 +	slouken@devolution.com
    5.24 +*/
    5.25 +
    5.26 +#ifdef SAVE_RCSID
    5.27 +static char rcsid =
    5.28 + "@(#) $Id$";
    5.29 +#endif
    5.30 +
    5.31 +/* Handle the event stream, converting console events into SDL events */
    5.32 +
    5.33 +#include <sys/types.h>
    5.34 +#include <sys/time.h>
    5.35 +#include <sys/ioctl.h>
    5.36 +#include <stdlib.h>
    5.37 +#include <stdio.h>
    5.38 +#include <unistd.h>
    5.39 +#include <fcntl.h>
    5.40 +#include <string.h>
    5.41 +#include <errno.h>
    5.42 +#include <limits.h>
    5.43 +
    5.44 +/* For parsing /proc */
    5.45 +#include <dirent.h>
    5.46 +#include <ctype.h>
    5.47 +
    5.48 +#include <linux/vt.h>
    5.49 +#include <linux/kd.h>
    5.50 +#include <linux/keyboard.h>
    5.51 +
    5.52 +#include "SDL.h"
    5.53 +#include "SDL_mutex.h"
    5.54 +#include "SDL_sysevents.h"
    5.55 +#include "SDL_sysvideo.h"
    5.56 +#include "SDL_events_c.h"
    5.57 +#include "SDL_gsvideo.h"
    5.58 +#include "SDL_gsevents_c.h"
    5.59 +#include "SDL_gskeys.h"
    5.60 +
    5.61 +#ifndef GPM_NODE_FIFO
    5.62 +#define GPM_NODE_FIFO	"/dev/gpmdata"
    5.63 +#endif
    5.64 +
    5.65 +/* The translation tables from a console scancode to a SDL keysym */
    5.66 +#define NUM_VGAKEYMAPS	(1<<KG_CAPSSHIFT)
    5.67 +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
    5.68 +static SDLKey keymap[128];
    5.69 +static Uint16 keymap_temp[128]; /* only used at startup */
    5.70 +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);
    5.71 +
    5.72 +/* Ugh, we have to duplicate the kernel's keysym mapping code...
    5.73 +   Oh, it's not so bad. :-)
    5.74 +
    5.75 +   FIXME: Add keyboard LED handling code
    5.76 + */
    5.77 +static void GS_vgainitkeymaps(int fd)
    5.78 +{
    5.79 +	struct kbentry entry;
    5.80 +	int map, i;
    5.81 +
    5.82 +	/* Don't do anything if we are passed a closed keyboard */
    5.83 +	if ( fd < 0 ) {
    5.84 +		return;
    5.85 +	}
    5.86 +
    5.87 +	/* Load all the keysym mappings */
    5.88 +	for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {
    5.89 +		memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));
    5.90 +		for ( i=0; i<NR_KEYS; ++i ) {
    5.91 +			entry.kb_table = map;
    5.92 +			entry.kb_index = i;
    5.93 +			if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {
    5.94 +				/* fill keytemp. This replaces SDL_fbkeys.h */
    5.95 +				if ( (map == 0) && (i<128) ) {
    5.96 +					keymap_temp[i] = entry.kb_value;
    5.97 +				}
    5.98 +				/* The "Enter" key is a special case */
    5.99 +				if ( entry.kb_value == K_ENTER ) {
   5.100 +					entry.kb_value = K(KT_ASCII,13);
   5.101 +				}
   5.102 +				/* Handle numpad specially as well */
   5.103 +				if ( KTYP(entry.kb_value) == KT_PAD ) {
   5.104 +					switch ( entry.kb_value ) {
   5.105 +					case K_P0:
   5.106 +					case K_P1:
   5.107 +					case K_P2:
   5.108 +					case K_P3:
   5.109 +					case K_P4:
   5.110 +					case K_P5:
   5.111 +					case K_P6:
   5.112 +					case K_P7:
   5.113 +					case K_P8:
   5.114 +					case K_P9:
   5.115 +						vga_keymap[map][i]=entry.kb_value;
   5.116 +						vga_keymap[map][i]+= '0';
   5.117 +						break;
   5.118 +										case K_PPLUS:
   5.119 +						vga_keymap[map][i]=K(KT_ASCII,'+');
   5.120 +						break;
   5.121 +										case K_PMINUS:
   5.122 +						vga_keymap[map][i]=K(KT_ASCII,'-');
   5.123 +						break;
   5.124 +										case K_PSTAR:
   5.125 +						vga_keymap[map][i]=K(KT_ASCII,'*');
   5.126 +						break;
   5.127 +										case K_PSLASH:
   5.128 +						vga_keymap[map][i]=K(KT_ASCII,'/');
   5.129 +						break;
   5.130 +										case K_PENTER:
   5.131 +						vga_keymap[map][i]=K(KT_ASCII,'\r');
   5.132 +						break;
   5.133 +										case K_PCOMMA:
   5.134 +						vga_keymap[map][i]=K(KT_ASCII,',');
   5.135 +						break;
   5.136 +										case K_PDOT:
   5.137 +						vga_keymap[map][i]=K(KT_ASCII,'.');
   5.138 +						break;
   5.139 +					default:
   5.140 +						break;
   5.141 +					}
   5.142 +				}
   5.143 +				/* Do the normal key translation */
   5.144 +				if ( (KTYP(entry.kb_value) == KT_LATIN) ||
   5.145 +					 (KTYP(entry.kb_value) == KT_ASCII) ||
   5.146 +					 (KTYP(entry.kb_value) == KT_LETTER) ) {
   5.147 +					vga_keymap[map][i] = entry.kb_value;
   5.148 +				}
   5.149 +			}
   5.150 +		}
   5.151 +	}
   5.152 +}
   5.153 +
   5.154 +int GS_InGraphicsMode(_THIS)
   5.155 +{
   5.156 +	return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
   5.157 +}
   5.158 +
   5.159 +int GS_EnterGraphicsMode(_THIS)
   5.160 +{
   5.161 +	struct termios keyboard_termios;
   5.162 +
   5.163 +	/* Set medium-raw keyboard mode */
   5.164 +	if ( (keyboard_fd >= 0) && !GS_InGraphicsMode(this) ) {
   5.165 +
   5.166 +		/* Switch to the correct virtual terminal */
   5.167 +		if ( current_vt > 0 ) {
   5.168 +			struct vt_stat vtstate;
   5.169 +
   5.170 +			if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {
   5.171 +				saved_vt = vtstate.v_active;
   5.172 +			}
   5.173 +			if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) {
   5.174 +				ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
   5.175 +			}
   5.176 +		}
   5.177 +
   5.178 +		/* Set the terminal input mode */
   5.179 +		if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {
   5.180 +			SDL_SetError("Unable to get terminal attributes");
   5.181 +			if ( keyboard_fd > 0 ) {
   5.182 +				close(keyboard_fd);
   5.183 +			}
   5.184 +			keyboard_fd = -1;
   5.185 +			return(-1);
   5.186 +		}
   5.187 +		if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {
   5.188 +			SDL_SetError("Unable to get current keyboard mode");
   5.189 +			if ( keyboard_fd > 0 ) {
   5.190 +				close(keyboard_fd);
   5.191 +			}
   5.192 +			keyboard_fd = -1;
   5.193 +			return(-1);
   5.194 +		}
   5.195 +		keyboard_termios = saved_kbd_termios;
   5.196 +		keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
   5.197 +		keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
   5.198 +		keyboard_termios.c_cc[VMIN] = 0;
   5.199 +		keyboard_termios.c_cc[VTIME] = 0;
   5.200 +		if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
   5.201 +			GS_CloseKeyboard(this);
   5.202 +			SDL_SetError("Unable to set terminal attributes");
   5.203 +			return(-1);
   5.204 +		}
   5.205 +		/* This will fail if we aren't root or this isn't our tty */
   5.206 +		if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {
   5.207 +			GS_CloseKeyboard(this);
   5.208 +			SDL_SetError("Unable to set keyboard in raw mode");
   5.209 +			return(-1);
   5.210 +		}
   5.211 +		if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {
   5.212 +			GS_CloseKeyboard(this);
   5.213 +			SDL_SetError("Unable to set keyboard in graphics mode");
   5.214 +			return(-1);
   5.215 +		}
   5.216 +	}
   5.217 +	return(keyboard_fd);
   5.218 +}
   5.219 +
   5.220 +void GS_LeaveGraphicsMode(_THIS)
   5.221 +{
   5.222 +	if ( GS_InGraphicsMode(this) ) {
   5.223 +		ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
   5.224 +		ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
   5.225 +		tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
   5.226 +		saved_kbd_mode = -1;
   5.227 +
   5.228 +		/* Head back over to the original virtual terminal */
   5.229 +		if ( saved_vt > 0 ) {
   5.230 +			ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
   5.231 +		}
   5.232 +	}
   5.233 +}
   5.234 +
   5.235 +void GS_CloseKeyboard(_THIS)
   5.236 +{
   5.237 +	if ( keyboard_fd >= 0 ) {
   5.238 +		GS_LeaveGraphicsMode(this);
   5.239 +		if ( keyboard_fd > 0 ) {
   5.240 +			close(keyboard_fd);
   5.241 +		}
   5.242 +	}
   5.243 +	keyboard_fd = -1;
   5.244 +}
   5.245 +
   5.246 +int GS_OpenKeyboard(_THIS)
   5.247 +{
   5.248 +	/* Open only if not already opened */
   5.249 + 	if ( keyboard_fd < 0 ) {
   5.250 +		char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
   5.251 +		char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
   5.252 +		int i, tty0_fd;
   5.253 +
   5.254 +		/* Try to query for a free virtual terminal */
   5.255 +		tty0_fd = -1;
   5.256 +		for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
   5.257 +			tty0_fd = open(tty0[i], O_WRONLY, 0);
   5.258 +		}
   5.259 +		if ( tty0_fd < 0 ) {
   5.260 +			tty0_fd = dup(0); /* Maybe stdin is a VT? */
   5.261 +		}
   5.262 +		ioctl(tty0_fd, VT_OPENQRY, &current_vt);
   5.263 +		close(tty0_fd);
   5.264 +		if ( (geteuid() == 0) && (current_vt > 0) ) {
   5.265 +			for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) {
   5.266 +				char vtpath[12];
   5.267 +
   5.268 +				sprintf(vtpath, vcs[i], current_vt);
   5.269 +				keyboard_fd = open(vtpath, O_RDWR, 0);
   5.270 +#ifdef DEBUG_KEYBOARD
   5.271 +				fprintf(stderr, "vtpath = %s, fd = %d\n",
   5.272 +					vtpath, keyboard_fd);
   5.273 +#endif /* DEBUG_KEYBOARD */
   5.274 +
   5.275 +				/* This needs to be our controlling tty
   5.276 +				   so that the kernel ioctl() calls work
   5.277 +				*/
   5.278 +				if ( keyboard_fd >= 0 ) {
   5.279 +					tty0_fd = open("/dev/tty", O_RDWR, 0);
   5.280 +					if ( tty0_fd >= 0 ) {
   5.281 +						ioctl(tty0_fd, TIOCNOTTY, 0);
   5.282 +						close(tty0_fd);
   5.283 +					}
   5.284 +				}
   5.285 +			}
   5.286 +		}
   5.287 + 		if ( keyboard_fd < 0 ) {
   5.288 +			/* Last resort, maybe our tty is a usable VT */
   5.289 +			current_vt = 0;
   5.290 +			keyboard_fd = open("/dev/tty", O_RDWR);
   5.291 + 		}
   5.292 +#ifdef DEBUG_KEYBOARD
   5.293 +		fprintf(stderr, "Current VT: %d\n", current_vt);
   5.294 +#endif
   5.295 + 		saved_kbd_mode = -1;
   5.296 +
   5.297 +		/* Make sure that our input is a console terminal */
   5.298 +		{ int dummy;
   5.299 +		  if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {
   5.300 +			close(keyboard_fd);
   5.301 +			keyboard_fd = -1;
   5.302 +			SDL_SetError("Unable to open a console terminal");
   5.303 +		  }
   5.304 +		}
   5.305 +
   5.306 +		/* Set up keymap */
   5.307 +		GS_vgainitkeymaps(keyboard_fd);
   5.308 + 	}
   5.309 + 	return(keyboard_fd);
   5.310 +}
   5.311 +
   5.312 +static enum {
   5.313 +	MOUSE_NONE = -1,
   5.314 +	MOUSE_GPM,	/* Note: GPM uses the MSC protocol */
   5.315 +	MOUSE_PS2,
   5.316 +	MOUSE_IMPS2,
   5.317 +	MOUSE_MS,
   5.318 +	MOUSE_BM,
   5.319 +	NUM_MOUSE_DRVS
   5.320 +} mouse_drv = MOUSE_NONE;
   5.321 +
   5.322 +void GS_CloseMouse(_THIS)
   5.323 +{
   5.324 +	if ( mouse_fd > 0 ) {
   5.325 +		close(mouse_fd);
   5.326 +	}
   5.327 +	mouse_fd = -1;
   5.328 +}
   5.329 +
   5.330 +/* Returns processes listed in /proc with the desired name */
   5.331 +static int find_pid(DIR *proc, const char *wanted_name)
   5.332 +{
   5.333 +	struct dirent *entry;
   5.334 +	int pid;
   5.335 +
   5.336 +	/* First scan proc for the gpm process */
   5.337 +	pid = 0;
   5.338 +	while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {
   5.339 +		if ( isdigit(entry->d_name[0]) ) {
   5.340 +			FILE *status;
   5.341 +			char path[PATH_MAX];
   5.342 +			char name[PATH_MAX];
   5.343 +
   5.344 +			sprintf(path, "/proc/%s/status", entry->d_name);
   5.345 +			status=fopen(path, "r");
   5.346 +			if ( status ) {
   5.347 +				name[0] = '\0';
   5.348 +				fscanf(status, "Name: %s", name);
   5.349 +				if ( strcmp(name, wanted_name) == 0 ) {
   5.350 +					pid = atoi(entry->d_name);
   5.351 +				}
   5.352 +				fclose(status);
   5.353 +			}
   5.354 +		}
   5.355 +	}
   5.356 +	return pid;
   5.357 +}
   5.358 +
   5.359 +/* Returns true if /dev/gpmdata is being written to by gpm */
   5.360 +static int gpm_available(void)
   5.361 +{
   5.362 +	int available;
   5.363 +	DIR *proc;
   5.364 +	int pid;
   5.365 +	int cmdline, len, arglen;
   5.366 +	char path[PATH_MAX];
   5.367 +	char args[PATH_MAX], *arg;
   5.368 +
   5.369 +	/* Don't bother looking if the fifo isn't there */
   5.370 +	if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {
   5.371 +		return(0);
   5.372 +	}
   5.373 +
   5.374 +	available = 0;
   5.375 +	proc = opendir("/proc");
   5.376 +	if ( proc ) {
   5.377 +		while ( (pid=find_pid(proc, "gpm")) > 0 ) {
   5.378 +			sprintf(path, "/proc/%d/cmdline", pid);
   5.379 +			cmdline = open(path, O_RDONLY, 0);
   5.380 +			if ( cmdline >= 0 ) {
   5.381 +				len = read(cmdline, args, sizeof(args));
   5.382 +				arg = args;
   5.383 +				while ( len > 0 ) {
   5.384 +					if ( strcmp(arg, "-R") == 0 ) {
   5.385 +						available = 1;
   5.386 +					}
   5.387 +					arglen = strlen(arg)+1;
   5.388 +					len -= arglen;
   5.389 +					arg += arglen;
   5.390 +				}
   5.391 +				close(cmdline);
   5.392 +			}
   5.393 +		}
   5.394 +		closedir(proc);
   5.395 +	}
   5.396 +	return available;
   5.397 +}
   5.398 +
   5.399 +
   5.400 +/* rcg06112001 Set up IMPS/2 mode, if possible. This gives
   5.401 + *  us access to the mousewheel, etc. Returns zero if
   5.402 + *  writes to device failed, but you still need to query the
   5.403 + *  device to see which mode it's actually in.
   5.404 + */
   5.405 +static int set_imps2_mode(int fd)
   5.406 +{
   5.407 +	/* If you wanted to control the mouse mode (and we do :)  ) ...
   5.408 +		Set IMPS/2 protocol:
   5.409 +			{0xf3,200,0xf3,100,0xf3,80}
   5.410 +		Reset mouse device:
   5.411 +			{0xFF}
   5.412 +	*/
   5.413 +	Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
   5.414 +	Uint8 reset = 0xff;
   5.415 +	fd_set fdset;
   5.416 +	struct timeval tv;
   5.417 +	int retval = 0;
   5.418 +
   5.419 +	if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
   5.420 +		if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
   5.421 +			retval = 1;
   5.422 +		}
   5.423 +	}
   5.424 +
   5.425 +	/* Get rid of any chatter from the above */
   5.426 +	FD_ZERO(&fdset);
   5.427 +	FD_SET(fd, &fdset);
   5.428 +	tv.tv_sec = 0;
   5.429 +	tv.tv_usec = 0;
   5.430 +	while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
   5.431 +		char temp[32];
   5.432 +		read(fd, temp, sizeof(temp));
   5.433 +	}
   5.434 +
   5.435 +	return retval;
   5.436 +}
   5.437 +
   5.438 +
   5.439 +/* Returns true if the mouse uses the IMPS/2 protocol */
   5.440 +static int detect_imps2(int fd)
   5.441 +{
   5.442 +	int imps2;
   5.443 +
   5.444 +	imps2 = 0;
   5.445 +
   5.446 +	if ( getenv("SDL_MOUSEDEV_IMPS2") ) {
   5.447 +		imps2 = 1;
   5.448 +	}
   5.449 +	if ( ! imps2 ) {
   5.450 +		Uint8 query_ps2 = 0xF2;
   5.451 +		fd_set fdset;
   5.452 +		struct timeval tv;
   5.453 +
   5.454 +		/* Get rid of any mouse motion noise */
   5.455 +		FD_ZERO(&fdset);
   5.456 +		FD_SET(fd, &fdset);
   5.457 +		tv.tv_sec = 0;
   5.458 +		tv.tv_usec = 0;
   5.459 +		while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
   5.460 +			char temp[32];
   5.461 +			read(fd, temp, sizeof(temp));
   5.462 +		}
   5.463 +
   5.464 +   		/* Query for the type of mouse protocol */
   5.465 +   		if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
   5.466 +   			Uint8 ch = 0;
   5.467 +
   5.468 +			/* Get the mouse protocol response */
   5.469 +			do {
   5.470 +				FD_ZERO(&fdset);
   5.471 +				FD_SET(fd, &fdset);
   5.472 +				tv.tv_sec = 1;
   5.473 +				tv.tv_usec = 0;
   5.474 +				if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) {
   5.475 +					break;
   5.476 +				}
   5.477 +			} while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&
   5.478 +			          ((ch == 0xFA) || (ch == 0xAA)) );
   5.479 +
   5.480 +			/* Experimental values (Logitech wheelmouse) */
   5.481 +#ifdef DEBUG_MOUSE
   5.482 +fprintf(stderr, "Last mouse mode: 0x%x\n", ch);
   5.483 +#endif
   5.484 +			if ( ch == 3 ) {
   5.485 +				imps2 = 1;
   5.486 +			}
   5.487 +		}
   5.488 +	}
   5.489 +	return imps2;
   5.490 +}
   5.491 +
   5.492 +int GS_OpenMouse(_THIS)
   5.493 +{
   5.494 +	int i;
   5.495 +	const char *mousedev;
   5.496 +	const char *mousedrv;
   5.497 +
   5.498 +	mousedrv = getenv("SDL_MOUSEDRV");
   5.499 +	mousedev = getenv("SDL_MOUSEDEV");
   5.500 +	mouse_fd = -1;
   5.501 +
   5.502 +	/* STD MICE */
   5.503 +
   5.504 +	if ( mousedev == NULL ) {
   5.505 +		/* FIXME someday... allow multiple mice in this driver */
   5.506 +		char *ps2mice[] = {
   5.507 +		    "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
   5.508 +		};
   5.509 +		/* First try to use GPM in repeater mode */
   5.510 +		if ( mouse_fd < 0 ) {
   5.511 +			if ( gpm_available() ) {
   5.512 +				mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0);
   5.513 +				if ( mouse_fd >= 0 ) {
   5.514 +#ifdef DEBUG_MOUSE
   5.515 +fprintf(stderr, "Using GPM mouse\n");
   5.516 +#endif
   5.517 +					mouse_drv = MOUSE_GPM;
   5.518 +				}
   5.519 +			}
   5.520 +		}
   5.521 +		/* Now try to use a modern PS/2 mouse */
   5.522 +		for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) {
   5.523 +			mouse_fd = open(ps2mice[i], O_RDWR, 0);
   5.524 +			if (mouse_fd < 0) {
   5.525 +				mouse_fd = open(ps2mice[i], O_RDONLY, 0);
   5.526 +			}
   5.527 +			if (mouse_fd >= 0) {
   5.528 +				/* rcg06112001 Attempt to set IMPS/2 mode */
   5.529 +				if ( i == 0 ) {
   5.530 +					set_imps2_mode(mouse_fd);
   5.531 +				}
   5.532 +				if (detect_imps2(mouse_fd)) {
   5.533 +#ifdef DEBUG_MOUSE
   5.534 +fprintf(stderr, "Using IMPS2 mouse\n");
   5.535 +#endif
   5.536 +					mouse_drv = MOUSE_IMPS2;
   5.537 +				} else {
   5.538 +					mouse_drv = MOUSE_PS2;
   5.539 +#ifdef DEBUG_MOUSE
   5.540 +fprintf(stderr, "Using PS2 mouse\n");
   5.541 +#endif
   5.542 +				}
   5.543 +			}
   5.544 +		}
   5.545 +		/* Next try to use a PPC ADB port mouse */
   5.546 +		if ( mouse_fd < 0 ) {
   5.547 +			mouse_fd = open("/dev/adbmouse", O_RDONLY, 0);
   5.548 +			if ( mouse_fd >= 0 ) {
   5.549 +#ifdef DEBUG_MOUSE
   5.550 +fprintf(stderr, "Using ADB mouse\n");
   5.551 +#endif
   5.552 +				mouse_drv = MOUSE_BM;
   5.553 +			}
   5.554 +		}
   5.555 +	}
   5.556 +	/* Default to a serial Microsoft mouse */
   5.557 +	if ( mouse_fd < 0 ) {
   5.558 +		if ( mousedev == NULL ) {
   5.559 +			mousedev = "/dev/mouse";
   5.560 +		}
   5.561 +		mouse_fd = open(mousedev, O_RDONLY, 0);
   5.562 +		if ( mouse_fd >= 0 ) {
   5.563 +			struct termios mouse_termios;
   5.564 +
   5.565 +			/* Set the sampling speed to 1200 baud */
   5.566 +			tcgetattr(mouse_fd, &mouse_termios);
   5.567 +			mouse_termios.c_iflag = IGNBRK | IGNPAR;
   5.568 +			mouse_termios.c_oflag = 0;
   5.569 +			mouse_termios.c_lflag = 0;
   5.570 +			mouse_termios.c_line = 0;
   5.571 +			mouse_termios.c_cc[VTIME] = 0;
   5.572 +			mouse_termios.c_cc[VMIN] = 1;
   5.573 +			mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
   5.574 +			mouse_termios.c_cflag |= CS8;
   5.575 +			mouse_termios.c_cflag |= B1200;
   5.576 +			tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios);
   5.577 +#ifdef DEBUG_MOUSE
   5.578 +fprintf(stderr, "Using Microsoft mouse on %s\n", mousedev);
   5.579 +#endif
   5.580 +			mouse_drv = MOUSE_MS;
   5.581 +		}
   5.582 +	}
   5.583 +	if ( mouse_fd < 0 ) {
   5.584 +		mouse_drv = MOUSE_NONE;
   5.585 +	}
   5.586 +	return(mouse_fd);
   5.587 +}
   5.588 +
   5.589 +static int posted = 0;
   5.590 +
   5.591 +void GS_vgamousecallback(int button, int dx, int dy)
   5.592 +{
   5.593 +	int button_1, button_3;
   5.594 +	int button_state;
   5.595 +	int state_changed;
   5.596 +	int i;
   5.597 +	Uint8 state;
   5.598 +
   5.599 +	if ( dx || dy ) {
   5.600 +		posted += SDL_PrivateMouseMotion(0, 1, dx, dy);
   5.601 +	}
   5.602 +
   5.603 +	/* Swap button 1 and 3 */
   5.604 +	button_1 = (button & 0x04) >> 2;
   5.605 +	button_3 = (button & 0x01) << 2;
   5.606 +	button &= ~0x05;
   5.607 +	button |= (button_1|button_3);
   5.608 +
   5.609 +	/* See what changed */
   5.610 +	button_state = SDL_GetMouseState(NULL, NULL);
   5.611 +	state_changed = button_state ^ button;
   5.612 +	for ( i=0; i<8; ++i ) {
   5.613 +		if ( state_changed & (1<<i) ) {
   5.614 +			if ( button & (1<<i) ) {
   5.615 +				state = SDL_PRESSED;
   5.616 +			} else {
   5.617 +				state = SDL_RELEASED;
   5.618 +			}
   5.619 +			posted += SDL_PrivateMouseButton(state, i+1, 0, 0);
   5.620 +		}
   5.621 +	}
   5.622 +}
   5.623 +
   5.624 +/* For now, use GPM, PS/2, and MS protocols
   5.625 +   Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
   5.626 + */
   5.627 +static void handle_mouse(_THIS)
   5.628 +{
   5.629 +	static int start = 0;
   5.630 +	static unsigned char mousebuf[BUFSIZ];
   5.631 +	int i, nread;
   5.632 +	int button = 0;
   5.633 +	int dx = 0, dy = 0;
   5.634 +	int packetsize = 0;
   5.635 +
   5.636 +	/* Figure out the mouse packet size */
   5.637 +	switch (mouse_drv) {
   5.638 +		case MOUSE_NONE:
   5.639 +			/* Ack! */
   5.640 +			read(mouse_fd, mousebuf, BUFSIZ);
   5.641 +			return;
   5.642 +		case MOUSE_GPM:
   5.643 +			packetsize = 5;
   5.644 +			break;
   5.645 +		case MOUSE_IMPS2:
   5.646 +			packetsize = 4;
   5.647 +			break;
   5.648 +		case MOUSE_PS2:
   5.649 +		case MOUSE_MS:
   5.650 +		case MOUSE_BM:
   5.651 +			packetsize = 3;
   5.652 +			break;
   5.653 +		case NUM_MOUSE_DRVS:
   5.654 +			/* Uh oh.. */
   5.655 +			packetsize = 0;
   5.656 +			break;
   5.657 +	}
   5.658 +
   5.659 +	/* Read as many packets as possible */
   5.660 +	nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start);
   5.661 +	if ( nread < 0 ) {
   5.662 +		return;
   5.663 +	}
   5.664 +	nread += start;
   5.665 +#ifdef DEBUG_MOUSE
   5.666 +	fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
   5.667 +#endif
   5.668 +	for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) {
   5.669 +		switch (mouse_drv) {
   5.670 +			case MOUSE_NONE:
   5.671 +				break;
   5.672 +			case MOUSE_GPM:
   5.673 +				/* GPM protocol has 0x80 in high byte */
   5.674 +				if ( (mousebuf[i] & 0xF8) != 0x80 ) {
   5.675 +					/* Go to next byte */
   5.676 +					i -= (packetsize-1);
   5.677 +					continue;
   5.678 +				}
   5.679 +				/* Get current mouse state */
   5.680 +				button = (~mousebuf[i]) & 0x07;
   5.681 +				dx =   (signed char)(mousebuf[i+1]) +
   5.682 +				       (signed char)(mousebuf[i+3]);
   5.683 +				dy = -((signed char)(mousebuf[i+2]) +
   5.684 +				       (signed char)(mousebuf[i+4]));
   5.685 +				break;
   5.686 +			case MOUSE_PS2:
   5.687 +				/* PS/2 protocol has nothing in high byte */
   5.688 +				if ( (mousebuf[i] & 0xC0) != 0 ) {
   5.689 +					/* Go to next byte */
   5.690 +					i -= (packetsize-1);
   5.691 +					continue;
   5.692 +				}
   5.693 +				/* Get current mouse state */
   5.694 +				button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
   5.695 +		  			 (mousebuf[i] & 0x02) >> 1 | /*Right*/
   5.696 +		  			 (mousebuf[i] & 0x01) << 2;  /*Left*/
   5.697 +		  		dx = (mousebuf[i] & 0x10) ?
   5.698 +		  		      mousebuf[i+1] - 256 : mousebuf[i+1];
   5.699 +		  		dy = (mousebuf[i] & 0x20) ?
   5.700 +		  		      -(mousebuf[i+2] - 256) : -mousebuf[i+2];
   5.701 +				break;
   5.702 +			case MOUSE_IMPS2:
   5.703 +				/* Get current mouse state */
   5.704 +				button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
   5.705 +		  			 (mousebuf[i] & 0x02) >> 1 | /*Right*/
   5.706 +		  			 (mousebuf[i] & 0x01) << 2 | /*Left*/
   5.707 +		  			 (mousebuf[i] & 0x40) >> 3 | /* 4 */
   5.708 +		  			 (mousebuf[i] & 0x80) >> 3;  /* 5 */
   5.709 +		  		dx = (mousebuf[i] & 0x10) ?
   5.710 +		  		      mousebuf[i+1] - 256 : mousebuf[i+1];
   5.711 +		  		dy = (mousebuf[i] & 0x20) ?
   5.712 +		  		      -(mousebuf[i+2] - 256) : -mousebuf[i+2];
   5.713 +				switch (mousebuf[i+3]&0x0F) {
   5.714 +				    case 0x0E: /* DX = +1 */
   5.715 +				    case 0x02: /* DX = -1 */
   5.716 +					break;
   5.717 +				    case 0x0F: /* DY = +1 (map button 4) */
   5.718 +					button |= (1<<3);
   5.719 +					break;
   5.720 +				    case 0x01: /* DY = -1 (map button 5) */
   5.721 +					button |= (1<<4);
   5.722 +					break;
   5.723 +				}
   5.724 +				break;
   5.725 +			case MOUSE_MS:
   5.726 +				/* Microsoft protocol has 0x40 in high byte */
   5.727 +				if ( (mousebuf[i] & 0x40) != 0x40 ) {
   5.728 +					/* Go to next byte */
   5.729 +					i -= (packetsize-1);
   5.730 +					continue;
   5.731 +				}
   5.732 +				/* Get current mouse state */
   5.733 +				button = ((mousebuf[i] & 0x20) >> 3) |
   5.734 +				         ((mousebuf[i] & 0x10) >> 4);
   5.735 +				dx = (signed char)(((mousebuf[i] & 0x03) << 6) |
   5.736 +				                   (mousebuf[i + 1] & 0x3F));
   5.737 +				dy = (signed char)(((mousebuf[i] & 0x0C) << 4) |
   5.738 +				                    (mousebuf[i + 2] & 0x3F));
   5.739 +				break;
   5.740 +			case MOUSE_BM:
   5.741 +				/* BusMouse protocol has 0xF8 in high byte */
   5.742 +				if ( (mousebuf[i] & 0xF8) != 0x80 ) {
   5.743 +					/* Go to next byte */
   5.744 +					i -= (packetsize-1);
   5.745 +					continue;
   5.746 +				}
   5.747 +				/* Get current mouse state */
   5.748 +				button = (~mousebuf[i]) & 0x07;
   5.749 +				dx =  (signed char)mousebuf[i+1];
   5.750 +				dy = -(signed char)mousebuf[i+2];
   5.751 +				break;
   5.752 +			case NUM_MOUSE_DRVS:
   5.753 +				/* Uh oh.. */
   5.754 +				dx = 0;
   5.755 +				dy = 0;
   5.756 +				break;
   5.757 +		}
   5.758 +		GS_vgamousecallback(button, dx, dy);
   5.759 +	}
   5.760 +	if ( i < nread ) {
   5.761 +		memcpy(mousebuf, &mousebuf[i], (nread-i));
   5.762 +		start = (nread-i);
   5.763 +	} else {
   5.764 +		start = 0;
   5.765 +	}
   5.766 +	return;
   5.767 +}
   5.768 +
   5.769 +static void handle_keyboard(_THIS)
   5.770 +{
   5.771 +	unsigned char keybuf[BUFSIZ];
   5.772 +	int i, nread;
   5.773 +	int pressed;
   5.774 +	int scancode;
   5.775 +	SDL_keysym keysym;
   5.776 +
   5.777 +	nread = read(keyboard_fd, keybuf, BUFSIZ);
   5.778 +	for ( i=0; i<nread; ++i ) {
   5.779 +		scancode = keybuf[i] & 0x7F;
   5.780 +		if ( keybuf[i] & 0x80 ) {
   5.781 +			pressed = SDL_RELEASED;
   5.782 +		} else {
   5.783 +			pressed = SDL_PRESSED;
   5.784 +		}
   5.785 +		TranslateKey(scancode, &keysym);
   5.786 +		posted += SDL_PrivateKeyboard(pressed, &keysym);
   5.787 +	}
   5.788 +}
   5.789 +
   5.790 +void GS_PumpEvents(_THIS)
   5.791 +{
   5.792 +	fd_set fdset;
   5.793 +	int max_fd;
   5.794 +	static struct timeval zero;
   5.795 +
   5.796 +	do {
   5.797 +		posted = 0;
   5.798 +
   5.799 +		FD_ZERO(&fdset);
   5.800 +		max_fd = 0;
   5.801 +		if ( keyboard_fd >= 0 ) {
   5.802 +			FD_SET(keyboard_fd, &fdset);
   5.803 +			if ( max_fd < keyboard_fd ) {
   5.804 +				max_fd = keyboard_fd;
   5.805 +			}
   5.806 +		}
   5.807 +		if ( mouse_fd >= 0 ) {
   5.808 +			FD_SET(mouse_fd, &fdset);
   5.809 +			if ( max_fd < mouse_fd ) {
   5.810 +				max_fd = mouse_fd;
   5.811 +			}
   5.812 +		}
   5.813 +		if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) {
   5.814 +			if ( keyboard_fd >= 0 ) {
   5.815 +				if ( FD_ISSET(keyboard_fd, &fdset) ) {
   5.816 +					handle_keyboard(this);
   5.817 +				}
   5.818 +			}
   5.819 +			if ( mouse_fd >= 0 ) {
   5.820 +				if ( FD_ISSET(mouse_fd, &fdset) ) {
   5.821 +					handle_mouse(this);
   5.822 +				}
   5.823 +			}
   5.824 +		}
   5.825 +	} while ( posted );
   5.826 +}
   5.827 +
   5.828 +void GS_InitOSKeymap(_THIS)
   5.829 +{
   5.830 +	int i;
   5.831 +
   5.832 +	/* Initialize the Linux key translation table */
   5.833 +
   5.834 +	/* First get the ascii keys and others not well handled */
   5.835 +	for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
   5.836 +	  switch(i) {
   5.837 +	  /* These aren't handled by the x86 kernel keymapping (?) */
   5.838 +	  case SCANCODE_PRINTSCREEN:
   5.839 +	    keymap[i] = SDLK_PRINT;
   5.840 +	    break;
   5.841 +	  case SCANCODE_BREAK:
   5.842 +	    keymap[i] = SDLK_BREAK;
   5.843 +	    break;
   5.844 +	  case SCANCODE_BREAK_ALTERNATIVE:
   5.845 +	    keymap[i] = SDLK_PAUSE;
   5.846 +	    break;
   5.847 +	  case SCANCODE_LEFTSHIFT:
   5.848 +	    keymap[i] = SDLK_LSHIFT;
   5.849 +	    break;
   5.850 +	  case SCANCODE_RIGHTSHIFT:
   5.851 +	    keymap[i] = SDLK_RSHIFT;
   5.852 +	    break;
   5.853 +	  case SCANCODE_LEFTCONTROL:
   5.854 +	    keymap[i] = SDLK_LCTRL;
   5.855 +	    break;
   5.856 +	  case SCANCODE_RIGHTCONTROL:
   5.857 +	    keymap[i] = SDLK_RCTRL;
   5.858 +	    break;
   5.859 +	  case SCANCODE_RIGHTWIN:
   5.860 +	    keymap[i] = SDLK_RSUPER;
   5.861 +	    break;
   5.862 +	  case SCANCODE_LEFTWIN:
   5.863 +	    keymap[i] = SDLK_LSUPER;
   5.864 +	    break;
   5.865 +	  case 127:
   5.866 +	    keymap[i] = SDLK_MENU;
   5.867 +	    break;
   5.868 +	  /* this should take care of all standard ascii keys */
   5.869 +	  default:
   5.870 +	    keymap[i] = KVAL(vga_keymap[0][i]);
   5.871 +	    break;
   5.872 +          }
   5.873 +	}
   5.874 +	for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
   5.875 +	  switch(keymap_temp[i]) {
   5.876 +	    case K_F1:  keymap[i] = SDLK_F1;  break;
   5.877 +	    case K_F2:  keymap[i] = SDLK_F2;  break;
   5.878 +	    case K_F3:  keymap[i] = SDLK_F3;  break;
   5.879 +	    case K_F4:  keymap[i] = SDLK_F4;  break;
   5.880 +	    case K_F5:  keymap[i] = SDLK_F5;  break;
   5.881 +	    case K_F6:  keymap[i] = SDLK_F6;  break;
   5.882 +	    case K_F7:  keymap[i] = SDLK_F7;  break;
   5.883 +	    case K_F8:  keymap[i] = SDLK_F8;  break;
   5.884 +	    case K_F9:  keymap[i] = SDLK_F9;  break;
   5.885 +	    case K_F10: keymap[i] = SDLK_F10; break;
   5.886 +	    case K_F11: keymap[i] = SDLK_F11; break;
   5.887 +	    case K_F12: keymap[i] = SDLK_F12; break;
   5.888 +
   5.889 +	    case K_DOWN:  keymap[i] = SDLK_DOWN;  break;
   5.890 +	    case K_LEFT:  keymap[i] = SDLK_LEFT;  break;
   5.891 +	    case K_RIGHT: keymap[i] = SDLK_RIGHT; break;
   5.892 +	    case K_UP:    keymap[i] = SDLK_UP;    break;
   5.893 +
   5.894 +	    case K_P0:     keymap[i] = SDLK_KP0; break;
   5.895 +	    case K_P1:     keymap[i] = SDLK_KP1; break;
   5.896 +	    case K_P2:     keymap[i] = SDLK_KP2; break;
   5.897 +	    case K_P3:     keymap[i] = SDLK_KP3; break;
   5.898 +	    case K_P4:     keymap[i] = SDLK_KP4; break;
   5.899 +	    case K_P5:     keymap[i] = SDLK_KP5; break;
   5.900 +	    case K_P6:     keymap[i] = SDLK_KP6; break;
   5.901 +	    case K_P7:     keymap[i] = SDLK_KP7; break;
   5.902 +	    case K_P8:     keymap[i] = SDLK_KP8; break;
   5.903 +	    case K_P9:     keymap[i] = SDLK_KP9; break;
   5.904 +	    case K_PPLUS:  keymap[i] = SDLK_KP_PLUS; break;
   5.905 +	    case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break;
   5.906 +	    case K_PSTAR:  keymap[i] = SDLK_KP_MULTIPLY; break;
   5.907 +	    case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break;
   5.908 +	    case K_PENTER: keymap[i] = SDLK_KP_ENTER; break;
   5.909 +	    case K_PDOT:   keymap[i] = SDLK_KP_PERIOD; break;
   5.910 +
   5.911 +	    case K_SHIFT:  if ( keymap[i] != SDLK_RSHIFT )
   5.912 +	                     keymap[i] = SDLK_LSHIFT;
   5.913 +	                   break;
   5.914 +	    case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break;
   5.915 +	    case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break;
   5.916 +	    case K_CTRL:  if ( keymap[i] != SDLK_RCTRL )
   5.917 +	                     keymap[i] = SDLK_LCTRL;
   5.918 +	                   break;
   5.919 +	    case K_CTRLL:  keymap[i] = SDLK_LCTRL;  break;
   5.920 +	    case K_CTRLR:  keymap[i] = SDLK_RCTRL;  break;
   5.921 +	    case K_ALT:    keymap[i] = SDLK_LALT;   break;
   5.922 +	    case K_ALTGR:  keymap[i] = SDLK_RALT;   break;
   5.923 +
   5.924 +	    case K_INSERT: keymap[i] = SDLK_INSERT;   break;
   5.925 +	    case K_REMOVE: keymap[i] = SDLK_DELETE;   break;
   5.926 +	    case K_PGUP:   keymap[i] = SDLK_PAGEUP;   break;
   5.927 +	    case K_PGDN:   keymap[i] = SDLK_PAGEDOWN; break;
   5.928 +	    case K_FIND:   keymap[i] = SDLK_HOME;     break;
   5.929 +	    case K_SELECT: keymap[i] = SDLK_END;      break;
   5.930 +
   5.931 +	    case K_NUM:  keymap[i] = SDLK_NUMLOCK;   break;
   5.932 +	    case K_CAPS: keymap[i] = SDLK_CAPSLOCK;  break;
   5.933 +
   5.934 +	    case K_F13:   keymap[i] = SDLK_PRINT;     break;
   5.935 +	    case K_HOLD:  keymap[i] = SDLK_SCROLLOCK; break;
   5.936 +	    case K_PAUSE: keymap[i] = SDLK_PAUSE;     break;
   5.937 +
   5.938 +	    case 127: keymap[i] = SDLK_BACKSPACE; break;
   5.939 +	     
   5.940 +	    default: break;
   5.941 +	  }
   5.942 +	}
   5.943 +}
   5.944 +
   5.945 +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym)
   5.946 +{
   5.947 +	/* Set the keysym information */
   5.948 +	keysym->scancode = scancode;
   5.949 +	keysym->sym = keymap[scancode];
   5.950 +	keysym->mod = KMOD_NONE;
   5.951 +
   5.952 +	/* If UNICODE is on, get the UNICODE value for the key */
   5.953 +	keysym->unicode = 0;
   5.954 +	if ( SDL_TranslateUNICODE ) {
   5.955 +		int map;
   5.956 +		SDLMod modstate;
   5.957 +
   5.958 +		modstate = SDL_GetModState();
   5.959 +		map = 0;
   5.960 +		if ( modstate & KMOD_SHIFT ) {
   5.961 +			map |= (1<<KG_SHIFT);
   5.962 +		}
   5.963 +		if ( modstate & KMOD_CTRL ) {
   5.964 +			map |= (1<<KG_CTRL);
   5.965 +		}
   5.966 +		if ( modstate & KMOD_ALT ) {
   5.967 +			map |= (1<<KG_ALT);
   5.968 +		}
   5.969 +		if ( modstate & KMOD_MODE ) {
   5.970 +			map |= (1<<KG_ALTGR);
   5.971 +		}
   5.972 +		if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) {
   5.973 +			if ( modstate & KMOD_CAPS ) {
   5.974 +				map ^= (1<<KG_SHIFT);
   5.975 +			}
   5.976 +		}
   5.977 +		if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) {
   5.978 +			if ( modstate & KMOD_NUM ) {
   5.979 +				keysym->unicode=KVAL(vga_keymap[map][scancode]);
   5.980 +			}
   5.981 +		} else {
   5.982 +			keysym->unicode = KVAL(vga_keymap[map][scancode]);
   5.983 +		}
   5.984 +	}
   5.985 +	return(keysym);
   5.986 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/video/ps2gs/SDL_gsevents_c.h	Sat Jun 16 03:17:45 2001 +0000
     6.3 @@ -0,0 +1,42 @@
     6.4 +/*
     6.5 +    SDL - Simple DirectMedia Layer
     6.6 +    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
     6.7 +
     6.8 +    This library is free software; you can redistribute it and/or
     6.9 +    modify it under the terms of the GNU Library General Public
    6.10 +    License as published by the Free Software Foundation; either
    6.11 +    version 2 of the License, or (at your option) any later version.
    6.12 +
    6.13 +    This library is distributed in the hope that it will be useful,
    6.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    6.16 +    Library General Public License for more details.
    6.17 +
    6.18 +    You should have received a copy of the GNU Library General Public
    6.19 +    License along with this library; if not, write to the Free
    6.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.21 +
    6.22 +    Sam Lantinga
    6.23 +    slouken@devolution.com
    6.24 +*/
    6.25 +
    6.26 +#ifdef SAVE_RCSID
    6.27 +static char rcsid =
    6.28 + "@(#) $Id$";
    6.29 +#endif
    6.30 +
    6.31 +#include "SDL_gsvideo.h"
    6.32 +
    6.33 +/* Variables and functions exported by SDL_sysevents.c to other parts 
    6.34 +   of the native video subsystem (SDL_sysvideo.c)
    6.35 +*/
    6.36 +extern int GS_OpenKeyboard(_THIS);
    6.37 +extern void GS_CloseKeyboard(_THIS);
    6.38 +extern int GS_OpenMouse(_THIS);
    6.39 +extern void GS_CloseMouse(_THIS);
    6.40 +extern int GS_EnterGraphicsMode(_THIS);
    6.41 +extern int GS_InGraphicsMode(_THIS);
    6.42 +extern void GS_LeaveGraphicsMode(_THIS);
    6.43 +
    6.44 +extern void GS_InitOSKeymap(_THIS);
    6.45 +extern void GS_PumpEvents(_THIS);
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/video/ps2gs/SDL_gskeys.h	Sat Jun 16 03:17:45 2001 +0000
     7.3 @@ -0,0 +1,139 @@
     7.4 +
     7.5 +/* Scancodes for the Linux framebuffer console
     7.6 +   - Taken with thanks from SVGAlib 1.4.0
     7.7 +*/
     7.8 +
     7.9 +#define SCANCODE_ESCAPE			1
    7.10 +
    7.11 +#define SCANCODE_1			2
    7.12 +#define SCANCODE_2			3
    7.13 +#define SCANCODE_3			4
    7.14 +#define SCANCODE_4			5
    7.15 +#define SCANCODE_5			6
    7.16 +#define SCANCODE_6			7
    7.17 +#define SCANCODE_7			8
    7.18 +#define SCANCODE_8			9
    7.19 +#define SCANCODE_9			10
    7.20 +#define SCANCODE_0			11
    7.21 +
    7.22 +#define SCANCODE_MINUS			12
    7.23 +#define SCANCODE_EQUAL			13
    7.24 +
    7.25 +#define SCANCODE_BACKSPACE		14
    7.26 +#define SCANCODE_TAB			15
    7.27 +
    7.28 +#define SCANCODE_Q			16
    7.29 +#define SCANCODE_W			17
    7.30 +#define SCANCODE_E			18
    7.31 +#define SCANCODE_R			19
    7.32 +#define SCANCODE_T			20
    7.33 +#define SCANCODE_Y			21
    7.34 +#define SCANCODE_U			22
    7.35 +#define SCANCODE_I			23
    7.36 +#define SCANCODE_O			24
    7.37 +#define SCANCODE_P			25
    7.38 +#define SCANCODE_BRACKET_LEFT		26
    7.39 +#define SCANCODE_BRACKET_RIGHT		27
    7.40 +
    7.41 +#define SCANCODE_ENTER			28
    7.42 +
    7.43 +#define SCANCODE_LEFTCONTROL		29
    7.44 +
    7.45 +#define SCANCODE_A			30
    7.46 +#define SCANCODE_S			31
    7.47 +#define SCANCODE_D			32
    7.48 +#define SCANCODE_F			33
    7.49 +#define SCANCODE_G			34
    7.50 +#define SCANCODE_H			35
    7.51 +#define SCANCODE_J			36
    7.52 +#define SCANCODE_K			37
    7.53 +#define SCANCODE_L			38
    7.54 +#define SCANCODE_SEMICOLON		39
    7.55 +#define SCANCODE_APOSTROPHE		40
    7.56 +#define SCANCODE_GRAVE			41
    7.57 +
    7.58 +#define SCANCODE_LEFTSHIFT		42
    7.59 +#define SCANCODE_BACKSLASH		43
    7.60 +
    7.61 +#define SCANCODE_Z			44
    7.62 +#define SCANCODE_X			45
    7.63 +#define SCANCODE_C			46
    7.64 +#define SCANCODE_V			47
    7.65 +#define SCANCODE_B			48
    7.66 +#define SCANCODE_N			49
    7.67 +#define SCANCODE_M			50
    7.68 +#define SCANCODE_COMMA			51
    7.69 +#define SCANCODE_PERIOD			52
    7.70 +#define SCANCODE_SLASH			53
    7.71 +
    7.72 +#define SCANCODE_RIGHTSHIFT		54
    7.73 +#define SCANCODE_KEYPADMULTIPLY		55
    7.74 +
    7.75 +#define SCANCODE_LEFTALT		56
    7.76 +#define SCANCODE_SPACE			57
    7.77 +#define SCANCODE_CAPSLOCK		58
    7.78 +
    7.79 +#define SCANCODE_F1			59
    7.80 +#define SCANCODE_F2			60
    7.81 +#define SCANCODE_F3			61
    7.82 +#define SCANCODE_F4			62
    7.83 +#define SCANCODE_F5			63
    7.84 +#define SCANCODE_F6			64
    7.85 +#define SCANCODE_F7			65
    7.86 +#define SCANCODE_F8			66
    7.87 +#define SCANCODE_F9			67
    7.88 +#define SCANCODE_F10			68
    7.89 +
    7.90 +#define SCANCODE_NUMLOCK		69
    7.91 +#define SCANCODE_SCROLLLOCK		70
    7.92 +
    7.93 +#define SCANCODE_KEYPAD7		71
    7.94 +#define SCANCODE_CURSORUPLEFT		71
    7.95 +#define SCANCODE_KEYPAD8		72
    7.96 +#define SCANCODE_CURSORUP		72
    7.97 +#define SCANCODE_KEYPAD9		73
    7.98 +#define SCANCODE_CURSORUPRIGHT		73
    7.99 +#define SCANCODE_KEYPADMINUS		74
   7.100 +#define SCANCODE_KEYPAD4		75
   7.101 +#define SCANCODE_CURSORLEFT		75
   7.102 +#define SCANCODE_KEYPAD5		76
   7.103 +#define SCANCODE_KEYPAD6		77
   7.104 +#define SCANCODE_CURSORRIGHT		77
   7.105 +#define SCANCODE_KEYPADPLUS		78
   7.106 +#define SCANCODE_KEYPAD1		79
   7.107 +#define SCANCODE_CURSORDOWNLEFT		79
   7.108 +#define SCANCODE_KEYPAD2		80
   7.109 +#define SCANCODE_CURSORDOWN		80
   7.110 +#define SCANCODE_KEYPAD3		81
   7.111 +#define SCANCODE_CURSORDOWNRIGHT	81
   7.112 +#define SCANCODE_KEYPAD0		82
   7.113 +#define SCANCODE_KEYPADPERIOD		83
   7.114 +
   7.115 +#define SCANCODE_LESS			86
   7.116 +
   7.117 +#define SCANCODE_F11			87
   7.118 +#define SCANCODE_F12			88
   7.119 +
   7.120 +#define SCANCODE_KEYPADENTER		96
   7.121 +#define SCANCODE_RIGHTCONTROL		97
   7.122 +#define SCANCODE_CONTROL		97
   7.123 +#define SCANCODE_KEYPADDIVIDE		98
   7.124 +#define SCANCODE_PRINTSCREEN		99
   7.125 +#define SCANCODE_RIGHTALT		100
   7.126 +#define SCANCODE_BREAK			101	/* Beware: is 119     */
   7.127 +#define SCANCODE_BREAK_ALTERNATIVE	119	/* on some keyboards! */
   7.128 +
   7.129 +#define SCANCODE_HOME			102
   7.130 +#define SCANCODE_CURSORBLOCKUP		103	/* Cursor key block */
   7.131 +#define SCANCODE_PAGEUP			104
   7.132 +#define SCANCODE_CURSORBLOCKLEFT	105	/* Cursor key block */
   7.133 +#define SCANCODE_CURSORBLOCKRIGHT	106	/* Cursor key block */
   7.134 +#define SCANCODE_END			107
   7.135 +#define SCANCODE_CURSORBLOCKDOWN	108	/* Cursor key block */
   7.136 +#define SCANCODE_PAGEDOWN		109
   7.137 +#define SCANCODE_INSERT			110
   7.138 +#define SCANCODE_REMOVE			111
   7.139 +
   7.140 +#define SCANCODE_RIGHTWIN		126
   7.141 +#define SCANCODE_LEFTWIN		125
   7.142 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/video/ps2gs/SDL_gsmouse.c	Sat Jun 16 03:17:45 2001 +0000
     8.3 @@ -0,0 +1,146 @@
     8.4 +/*
     8.5 +    SDL - Simple DirectMedia Layer
     8.6 +    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
     8.7 +
     8.8 +    This library is free software; you can redistribute it and/or
     8.9 +    modify it under the terms of the GNU Library General Public
    8.10 +    License as published by the Free Software Foundation; either
    8.11 +    version 2 of the License, or (at your option) any later version.
    8.12 +
    8.13 +    This library is distributed in the hope that it will be useful,
    8.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    8.16 +    Library General Public License for more details.
    8.17 +
    8.18 +    You should have received a copy of the GNU Library General Public
    8.19 +    License along with this library; if not, write to the Free
    8.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.21 +
    8.22 +    Sam Lantinga
    8.23 +    slouken@devolution.com
    8.24 +*/
    8.25 +
    8.26 +#ifdef SAVE_RCSID
    8.27 +static char rcsid =
    8.28 + "@(#) $Id$";
    8.29 +#endif
    8.30 +
    8.31 +#include <stdlib.h>
    8.32 +#include <stdio.h>
    8.33 +#include <sys/ioctl.h>
    8.34 +
    8.35 +#include "SDL_error.h"
    8.36 +#include "SDL_mouse.h"
    8.37 +#include "SDL_events_c.h"
    8.38 +#include "SDL_cursor_c.h"
    8.39 +#include "SDL_gsvideo.h"
    8.40 +#include "SDL_gsmouse_c.h"
    8.41 +
    8.42 +
    8.43 +/* The implementation dependent data for the window manager cursor */
    8.44 +struct WMcursor {
    8.45 +	int unused;
    8.46 +};
    8.47 +
    8.48 +/* There isn't any implementation dependent data */
    8.49 +void GS_FreeWMCursor(_THIS, WMcursor *cursor)
    8.50 +{
    8.51 +	return;
    8.52 +}
    8.53 +
    8.54 +/* There isn't any implementation dependent data */
    8.55 +WMcursor *GS_CreateWMCursor(_THIS,
    8.56 +		Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
    8.57 +{
    8.58 +	return((WMcursor *)0x01);
    8.59 +}
    8.60 +
    8.61 +static void GS_MoveCursor(_THIS, SDL_Cursor *cursor, int x, int y)
    8.62 +{
    8.63 +	SDL_Surface *screen;
    8.64 +	struct ps2_image image;
    8.65 +	SDL_Rect area;
    8.66 +	int mouse_y1, mouse_y2;
    8.67 +	void *saved_pixels;
    8.68 +	int screen_updated;
    8.69 +
    8.70 +	/* Lock so we don't interrupt an update with mouse motion */
    8.71 +	SDL_LockCursor();
    8.72 +
    8.73 +	/* Make sure any pending DMA has completed */
    8.74 +	if ( dma_pending ) {
    8.75 +		ioctl(console_fd, PS2IOC_SENDQCT, 1);
    8.76 +		dma_pending = 0;
    8.77 +	}
    8.78 +
    8.79 +	/* Remove the cursor image from the DMA area */
    8.80 +	screen = this->screen;
    8.81 +	saved_pixels = screen->pixels;
    8.82 +	screen->pixels = mapped_mem + screen->offset;
    8.83 +	screen_updated = 0;
    8.84 +	if ( cursor_drawn ) {
    8.85 +		SDL_EraseCursorNoLock(this->screen);
    8.86 +		cursor_drawn = 0;
    8.87 +		screen_updated = 1;
    8.88 +	}
    8.89 +
    8.90 +	/* Save the current mouse area */
    8.91 +	SDL_MouseRect(&area);
    8.92 +	mouse_y1 = area.y;
    8.93 +	mouse_y2 = area.y+area.h;
    8.94 +
    8.95 +	/* Only draw the new cursor if there was one passed in */
    8.96 +	if ( cursor ) {
    8.97 +		/* Set the new location */
    8.98 +		cursor->area.x = (x - cursor->hot_x);
    8.99 +		cursor->area.y = (y - cursor->hot_y);
   8.100 +
   8.101 +		/* Draw the cursor at the new location */
   8.102 +		if ( (SDL_cursorstate & CURSOR_VISIBLE) && screen->pixels ) {
   8.103 +			SDL_DrawCursorNoLock(screen);
   8.104 +			cursor_drawn = 1;
   8.105 +			screen_updated = 1;
   8.106 +		}
   8.107 +	}
   8.108 +	screen->pixels = saved_pixels;
   8.109 +
   8.110 +	/* Update the affected area of the screen */
   8.111 +	if ( screen_updated ) {
   8.112 +		SDL_MouseRect(&area);
   8.113 +		if ( area.y < mouse_y1 ) {
   8.114 +			mouse_y1 = area.y;
   8.115 +		}
   8.116 +		if ( (area.y+area.h) > mouse_y2 ) {
   8.117 +			mouse_y2 = area.y+area.h;
   8.118 +		}
   8.119 +		image = screen_image;
   8.120 +		image.y = screen->offset / screen->pitch + mouse_y1;
   8.121 +		image.h = mouse_y2 - mouse_y1;
   8.122 +		image.ptr = mapped_mem + image.y * screen->pitch;
   8.123 +		ioctl(console_fd, PS2IOC_LOADIMAGE, &image);
   8.124 +	}
   8.125 +
   8.126 +	/* We're finished */
   8.127 +	SDL_UnlockCursor();
   8.128 +}
   8.129 +
   8.130 +void GS_MoveWMCursor(_THIS, int x, int y)
   8.131 +{
   8.132 +	GS_MoveCursor(this, SDL_cursor, x, y);
   8.133 +}
   8.134 +
   8.135 +int GS_ShowWMCursor(_THIS, WMcursor *wmcursor)
   8.136 +{
   8.137 +	SDL_Cursor *cursor;
   8.138 +	int x, y;
   8.139 +
   8.140 +	/* Draw the cursor at the appropriate location */
   8.141 +	SDL_GetMouseState(&x, &y);
   8.142 +	if ( wmcursor ) {
   8.143 +		cursor = SDL_cursor;
   8.144 +	} else {
   8.145 +		cursor = NULL;
   8.146 +	}
   8.147 +	GS_MoveCursor(this, cursor, x, y);
   8.148 +	return(1);
   8.149 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/video/ps2gs/SDL_gsmouse_c.h	Sat Jun 16 03:17:45 2001 +0000
     9.3 @@ -0,0 +1,43 @@
     9.4 +/*
     9.5 +    SDL - Simple DirectMedia Layer
     9.6 +    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
     9.7 +
     9.8 +    This library is free software; you can redistribute it and/or
     9.9 +    modify it under the terms of the GNU Library General Public
    9.10 +    License as published by the Free Software Foundation; either
    9.11 +    version 2 of the License, or (at your option) any later version.
    9.12 +
    9.13 +    This library is distributed in the hope that it will be useful,
    9.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    9.16 +    Library General Public License for more details.
    9.17 +
    9.18 +    You should have received a copy of the GNU Library General Public
    9.19 +    License along with this library; if not, write to the Free
    9.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.21 +
    9.22 +    Sam Lantinga
    9.23 +    slouken@devolution.com
    9.24 +*/
    9.25 +
    9.26 +#ifdef SAVE_RCSID
    9.27 +static char rcsid =
    9.28 + "@(#) $Id$";
    9.29 +#endif
    9.30 +
    9.31 +#include "SDL_gsvideo.h"
    9.32 +
    9.33 +/* This is the maximum size of the cursor sprite */
    9.34 +#define CURSOR_W	32
    9.35 +#define CURSOR_H	32
    9.36 +#define CURSOR_W_POW	5	/* 32 = 2^5 */
    9.37 +#define CURSOR_H_POW	5	/* 32 = 2^5 */
    9.38 +
    9.39 +/* Functions to be exported */
    9.40 +extern void GS_FreeWMCursor(_THIS, WMcursor *cursor);
    9.41 +extern WMcursor *GS_CreateWMCursor(_THIS,
    9.42 +		Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);
    9.43 +extern void GS_DrawCursor(SDL_Surface *screen);
    9.44 +extern void GS_EraseCursor(SDL_Surface *screen);
    9.45 +extern void GS_MoveWMCursor(_THIS, int x, int y);
    9.46 +extern int GS_ShowWMCursor(_THIS, WMcursor *cursor);
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/video/ps2gs/SDL_gsvideo.c	Sat Jun 16 03:17:45 2001 +0000
    10.3 @@ -0,0 +1,577 @@
    10.4 +/*
    10.5 +	SDL - Simple DirectMedia Layer
    10.6 +	Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
    10.7 +
    10.8 +	This library is free software; you can redistribute it and/or
    10.9 +	modify it under the terms of the GNU Library General Public
   10.10 +	License as published by the Free Software Foundation; either
   10.11 +	version 2 of the License, or (at your option) any later version.
   10.12 +
   10.13 +	This library is distributed in the hope that it will be useful,
   10.14 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.15 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   10.16 +	Library General Public License for more details.
   10.17 +
   10.18 +	You should have received a copy of the GNU Library General Public
   10.19 +	License along with this library; if not, write to the Free
   10.20 +	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   10.21 +
   10.22 +	Sam Lantinga
   10.23 +	slouken@devolution.com
   10.24 +*/
   10.25 +
   10.26 +#ifdef SAVE_RCSID
   10.27 +static char rcsid =
   10.28 + "@(#) $Id$";
   10.29 +#endif
   10.30 +
   10.31 +/* Framebuffer console based SDL video driver implementation.
   10.32 +*/
   10.33 +
   10.34 +#include <stdlib.h>
   10.35 +#include <stdio.h>
   10.36 +#include <fcntl.h>
   10.37 +#include <unistd.h>
   10.38 +#include <sys/ioctl.h>
   10.39 +#include <sys/mman.h>
   10.40 +
   10.41 +#include "SDL.h"
   10.42 +#include "SDL_error.h"
   10.43 +#include "SDL_video.h"
   10.44 +#include "SDL_mouse.h"
   10.45 +#include "SDL_sysvideo.h"
   10.46 +#include "SDL_pixels_c.h"
   10.47 +#include "SDL_events_c.h"
   10.48 +#include "SDL_cursor_c.h"
   10.49 +#include "SDL_gsvideo.h"
   10.50 +#include "SDL_gsmouse_c.h"
   10.51 +#include "SDL_gsevents_c.h"
   10.52 +#include "SDL_gsyuv_c.h"
   10.53 +
   10.54 +
   10.55 +/* Initialization/Query functions */
   10.56 +static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat);
   10.57 +static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
   10.58 +static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
   10.59 +static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
   10.60 +static void GS_VideoQuit(_THIS);
   10.61 +
   10.62 +/* Hardware surface functions */
   10.63 +static int GS_AllocHWSurface(_THIS, SDL_Surface *surface);
   10.64 +static int GS_LockHWSurface(_THIS, SDL_Surface *surface);
   10.65 +static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface);
   10.66 +static void GS_FreeHWSurface(_THIS, SDL_Surface *surface);
   10.67 +
   10.68 +/* GS driver bootstrap functions */
   10.69 +
   10.70 +static int GS_Available(void)
   10.71 +{
   10.72 +	int console, memory;
   10.73 +
   10.74 +	console = open(PS2_DEV_GS, O_RDWR, 0);
   10.75 +	if ( console >= 0 ) {
   10.76 +		close(console);
   10.77 +	}
   10.78 +	memory = open(PS2_DEV_MEM, O_RDWR, 0);
   10.79 +	if ( memory >= 0 ) {
   10.80 +		close(memory);
   10.81 +	}
   10.82 +	return((console >= 0) && (memory >= 0));
   10.83 +}
   10.84 +
   10.85 +static void GS_DeleteDevice(SDL_VideoDevice *device)
   10.86 +{
   10.87 +	free(device->hidden);
   10.88 +	free(device);
   10.89 +}
   10.90 +
   10.91 +static SDL_VideoDevice *GS_CreateDevice(int devindex)
   10.92 +{
   10.93 +	SDL_VideoDevice *this;
   10.94 +
   10.95 +	/* Initialize all variables that we clean on shutdown */
   10.96 +	this = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
   10.97 +	if ( this ) {
   10.98 +		memset(this, 0, (sizeof *this));
   10.99 +		this->hidden = (struct SDL_PrivateVideoData *)
  10.100 +				malloc((sizeof *this->hidden));
  10.101 +	}
  10.102 +	if ( (this == NULL) || (this->hidden == NULL) ) {
  10.103 +		SDL_OutOfMemory();
  10.104 +		if ( this ) {
  10.105 +			free(this);
  10.106 +		}
  10.107 +		return(0);
  10.108 +	}
  10.109 +	memset(this->hidden, 0, (sizeof *this->hidden));
  10.110 +	mouse_fd = -1;
  10.111 +	keyboard_fd = -1;
  10.112 +
  10.113 +	/* Set the function pointers */
  10.114 +	this->VideoInit = GS_VideoInit;
  10.115 +	this->ListModes = GS_ListModes;
  10.116 +	this->SetVideoMode = GS_SetVideoMode;
  10.117 +	this->CreateYUVOverlay = GS_CreateYUVOverlay;
  10.118 +	this->SetColors = GS_SetColors;
  10.119 +	this->UpdateRects = NULL;
  10.120 +	this->VideoQuit = GS_VideoQuit;
  10.121 +	this->AllocHWSurface = GS_AllocHWSurface;
  10.122 +	this->CheckHWBlit = NULL;
  10.123 +	this->FillHWRect = NULL;
  10.124 +	this->SetHWColorKey = NULL;
  10.125 +	this->SetHWAlpha = NULL;
  10.126 +	this->LockHWSurface = GS_LockHWSurface;
  10.127 +	this->UnlockHWSurface = GS_UnlockHWSurface;
  10.128 +	this->FlipHWSurface = NULL;
  10.129 +	this->FreeHWSurface = GS_FreeHWSurface;
  10.130 +	this->SetIcon = NULL;
  10.131 +	this->SetCaption = NULL;
  10.132 +	this->GetWMInfo = NULL;
  10.133 +	this->FreeWMCursor = GS_FreeWMCursor;
  10.134 +	this->CreateWMCursor = GS_CreateWMCursor;
  10.135 +	this->ShowWMCursor = GS_ShowWMCursor;
  10.136 +	this->MoveWMCursor = GS_MoveWMCursor;
  10.137 +	this->InitOSKeymap = GS_InitOSKeymap;
  10.138 +	this->PumpEvents = GS_PumpEvents;
  10.139 +
  10.140 +	this->free = GS_DeleteDevice;
  10.141 +
  10.142 +	return this;
  10.143 +}
  10.144 +
  10.145 +VideoBootStrap PS2GS_bootstrap = {
  10.146 +	"ps2gs", "PlayStation 2 Graphics Synthesizer",
  10.147 +	GS_Available, GS_CreateDevice
  10.148 +};
  10.149 +
  10.150 +/* These are the pixel formats for the 32, 24, and 16 bit video modes */
  10.151 +static struct {
  10.152 +	int bpp;
  10.153 +	Uint32 r;
  10.154 +	Uint32 g;
  10.155 +	Uint32 b;
  10.156 +} GS_pixelmasks[] = {
  10.157 +	{ 32, 0x000000FF,	/* RGB little-endian */
  10.158 +	      0x0000FF00,
  10.159 +	      0x00FF0000 },
  10.160 +	{ 24, 0x000000FF,	/* RGB little-endian */
  10.161 +	      0x0000FF00,
  10.162 +	      0x00FF0000 },
  10.163 +	{ 16, 0x0000001f,	/* RGB little-endian */
  10.164 +	      0x000003e0,
  10.165 +	      0x00007c00 },
  10.166 +};
  10.167 +/* This is a mapping from SDL bytes-per-pixel to GS pixel format */
  10.168 +static int GS_formatmap[] = {
  10.169 +	-1,		/* 0 bpp, not a legal value */
  10.170 +	-1,		/* 8 bpp, not supported (yet?) */
  10.171 +	PS2_GS_PSMCT16,	/* 16 bpp */
  10.172 +	PS2_GS_PSMCT24,	/* 24 bpp */
  10.173 +	PS2_GS_PSMCT32	/* 32 bpp */
  10.174 +};
  10.175 +
  10.176 +static unsigned long long head_tags[] __attribute__((aligned(16))) = {
  10.177 +	4 | (1LL << 60),	/* GIFtag */
  10.178 +	0x0e,			/* A+D */
  10.179 +	0,			/* 2 */
  10.180 +	PS2_GS_BITBLTBUF,
  10.181 +	0,			/* 4 */
  10.182 +	PS2_GS_TRXPOS,
  10.183 +	0,			/* 6 */
  10.184 +	PS2_GS_TRXREG,
  10.185 +	0,			/* 8 */
  10.186 +	PS2_GS_TRXDIR
  10.187 +};
  10.188 +
  10.189 +#define MAXIMG		(32767 * 16)
  10.190 +#define MAXTAGS		8
  10.191 +
  10.192 +static inline int loadimage_nonblock(int fd, struct ps2_image *image, int size,
  10.193 +                                     unsigned long long *hm,
  10.194 +                                     unsigned long long *im)
  10.195 +{
  10.196 +	struct ps2_plist plist;
  10.197 +	struct ps2_packet packet[1 + MAXTAGS * 2];
  10.198 +	int isize;
  10.199 +	int pnum, it, eop;
  10.200 +	char *data;
  10.201 +
  10.202 +	/* initialize the variables */
  10.203 +	data = (char *)image->ptr;
  10.204 +	pnum = it = eop = 0;
  10.205 +	plist.packet = packet;
  10.206 +
  10.207 +	/* make BITBLT packet */
  10.208 +	packet[pnum].ptr = hm;
  10.209 +	packet[pnum].len = sizeof(head_tags);
  10.210 +	pnum++;
  10.211 +	hm[2] = ((unsigned long long)image->fbp << 32) |
  10.212 +	        ((unsigned long long)image->fbw << 48) |
  10.213 +	        ((unsigned long long)image->psm << 56);
  10.214 +	hm[4] = ((unsigned long long)image->x << 32) |
  10.215 +	        ((unsigned long long)image->y << 48);
  10.216 +	hm[6] = (unsigned long long)image->w |
  10.217 +	        ((unsigned long long)image->h << 32);
  10.218 +
  10.219 +	/* make image mode tags */
  10.220 +	while (!eop) {
  10.221 +		isize = size > MAXIMG ? MAXIMG : size;
  10.222 +		size -= isize;
  10.223 +		eop = (size == 0);
  10.224 +
  10.225 +		packet[pnum].ptr = &im[it];
  10.226 +		packet[pnum].len = sizeof(unsigned long long) * 2;
  10.227 +		pnum++;
  10.228 +		im[it++] = (isize >> 4) | (eop ? (1 << 15) : 0) | (2LL << 58);
  10.229 +		im[it++] = 0;
  10.230 +
  10.231 +		packet[pnum].ptr = (void *)data;
  10.232 +		packet[pnum].len = isize;
  10.233 +		pnum++;
  10.234 +		data += isize;
  10.235 +	}
  10.236 +	plist.num = pnum;
  10.237 +
  10.238 +	return ioctl(fd, PS2IOC_SENDL, &plist);
  10.239 +}
  10.240 +
  10.241 +static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
  10.242 +{
  10.243 +	struct ps2_screeninfo vinfo;
  10.244 +
  10.245 +	/* Initialize the library */
  10.246 +	console_fd = open(PS2_DEV_GS, O_RDWR, 0);
  10.247 +	if ( console_fd < 0 ) {
  10.248 +		SDL_SetError("Unable to open %s", PS2_DEV_GS);
  10.249 +		return(-1);
  10.250 +	}
  10.251 +	memory_fd = open(PS2_DEV_MEM, O_RDWR, 0);
  10.252 +	if ( memory_fd < 0 ) {
  10.253 +		close(console_fd);
  10.254 +		console_fd = -1;
  10.255 +		SDL_SetError("Unable to open %s", PS2_DEV_MEM);
  10.256 +		return(-1);
  10.257 +	}
  10.258 +
  10.259 +	/* Determine the current screen depth */
  10.260 +	if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) {
  10.261 +		close(memory_fd);
  10.262 +		close(console_fd);
  10.263 +		console_fd = -1;
  10.264 +		SDL_SetError("Couldn't get console pixel format");
  10.265 +		return(-1);
  10.266 +	}
  10.267 +	if ( vinfo.mode != PS2_GS_VESA ) {
  10.268 +		GS_VideoQuit(this);
  10.269 +		SDL_SetError("Console must be in VESA video mode");
  10.270 +		return(-1);
  10.271 +	}
  10.272 +	switch (vinfo.psm) {
  10.273 +	    /* Supported pixel formats */
  10.274 +	    case PS2_GS_PSMCT32:
  10.275 +	    case PS2_GS_PSMCT24:
  10.276 +	    case PS2_GS_PSMCT16:
  10.277 +		break;
  10.278 +	    default:
  10.279 +		GS_VideoQuit(this);
  10.280 +		SDL_SetError("Unknown console pixel format: %d", vinfo.psm);
  10.281 +		return(-1);
  10.282 +	}
  10.283 +	vformat->BitsPerPixel = GS_pixelmasks[vinfo.psm].bpp;
  10.284 +	vformat->Rmask = GS_pixelmasks[vinfo.psm].r;
  10.285 +	vformat->Gmask = GS_pixelmasks[vinfo.psm].g;
  10.286 +	vformat->Bmask = GS_pixelmasks[vinfo.psm].b;
  10.287 +	saved_vinfo = vinfo;
  10.288 +
  10.289 +	/* Enable mouse and keyboard support */
  10.290 +	if ( GS_OpenKeyboard(this) < 0 ) {
  10.291 +		GS_VideoQuit(this);
  10.292 +		SDL_SetError("Unable to open keyboard");
  10.293 +		return(-1);
  10.294 +	}
  10.295 +	if ( GS_OpenMouse(this) < 0 ) {
  10.296 +		const char *sdl_nomouse;
  10.297 +
  10.298 +		sdl_nomouse = getenv("SDL_NOMOUSE");
  10.299 +		if ( ! sdl_nomouse ) {
  10.300 +			GS_VideoQuit(this);
  10.301 +			SDL_SetError("Unable to open mouse");
  10.302 +			return(-1);
  10.303 +		}
  10.304 +	}
  10.305 +
  10.306 +	/* We're done! */
  10.307 +	return(0);
  10.308 +}
  10.309 +
  10.310 +static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
  10.311 +{
  10.312 +	static SDL_Rect GS_mode_list[] = {
  10.313 +		{ 0, 0, 1280, 1024 },
  10.314 +		{ 0, 0, 1024, 768 },
  10.315 +		{ 0, 0, 800, 600 },
  10.316 +		{ 0, 0, 640, 480 }
  10.317 +	};
  10.318 +	static SDL_Rect *GS_modes[] = {
  10.319 +		&GS_mode_list[0],
  10.320 +		&GS_mode_list[1],
  10.321 +		&GS_mode_list[2],
  10.322 +		&GS_mode_list[3],
  10.323 +		NULL
  10.324 +	};
  10.325 +	SDL_Rect **modes;
  10.326 +
  10.327 +	switch (format->BitsPerPixel) {
  10.328 +	    case 16:
  10.329 +	    case 24:
  10.330 +	    case 32:
  10.331 +		modes = GS_modes;
  10.332 +		break;
  10.333 +	    default:
  10.334 +		modes = NULL;
  10.335 +		break;
  10.336 +	}
  10.337 +	return(modes);
  10.338 +}
  10.339 +
  10.340 +/* Various screen update functions available */
  10.341 +static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects);
  10.342 +
  10.343 +static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
  10.344 +				int width, int height, int bpp, Uint32 flags)
  10.345 +{
  10.346 +	struct ps2_screeninfo vinfo;
  10.347 +
  10.348 +	/* Set the terminal into graphics mode */
  10.349 +	if ( GS_EnterGraphicsMode(this) < 0 ) {
  10.350 +		return(NULL);
  10.351 +	}
  10.352 +
  10.353 +	/* Set the video mode and get the final screen format */
  10.354 +	if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) {
  10.355 +		SDL_SetError("Couldn't get console screen info");
  10.356 +		return(NULL);
  10.357 +	}
  10.358 +	if ( (vinfo.w != width) || (vinfo.h != height) ||
  10.359 +	     (GS_pixelmasks[vinfo.psm].bpp != bpp) ) {
  10.360 +		switch (width) {
  10.361 +		    case 640:
  10.362 +			vinfo.res = PS2_GS_640x480;
  10.363 +			break;
  10.364 +		    case 800:
  10.365 +			vinfo.res = PS2_GS_800x600;
  10.366 +			break;
  10.367 +		    case 1024:
  10.368 +			vinfo.res = PS2_GS_1024x768;
  10.369 +			break;
  10.370 +		    case 1280:
  10.371 +			vinfo.res = PS2_GS_1280x1024;
  10.372 +			break;
  10.373 +		    default:
  10.374 +			SDL_SetError("Unsupported resolution: %dx%d\n",
  10.375 +			             width, height);
  10.376 +			return(NULL);
  10.377 +		}
  10.378 +		vinfo.res |= (PS2_GS_75Hz << 8);
  10.379 +		vinfo.w = width;
  10.380 +		vinfo.h = height;
  10.381 +		vinfo.fbp = 0;
  10.382 +		vinfo.psm = GS_formatmap[bpp/8];
  10.383 +		if ( vinfo.psm < 0 ) {
  10.384 +			SDL_SetError("Unsupported depth: %d bpp\n", bpp);
  10.385 +			return(NULL);
  10.386 +		}
  10.387 +		if ( ioctl(console_fd, PS2IOC_SSCREENINFO, &vinfo) < 0 ) {
  10.388 +			SDL_SetError("Couldn't set console screen info");
  10.389 +			return(NULL);
  10.390 +		}
  10.391 +
  10.392 +		/* Unmap the previous DMA buffer */
  10.393 +		if ( mapped_mem ) {
  10.394 +			munmap(mapped_mem, mapped_len);
  10.395 +			mapped_mem = NULL;
  10.396 +		}
  10.397 +	}
  10.398 +	if ( ! SDL_ReallocFormat(current, GS_pixelmasks[vinfo.psm].bpp,
  10.399 +	                                  GS_pixelmasks[vinfo.psm].r,
  10.400 +	                                  GS_pixelmasks[vinfo.psm].g,
  10.401 +	                                  GS_pixelmasks[vinfo.psm].b, 0) ) {
  10.402 +		return(NULL);
  10.403 +	}
  10.404 +
  10.405 +	/* Set up the new mode framebuffer */
  10.406 +	current->flags = SDL_FULLSCREEN;
  10.407 +	current->w = vinfo.w;
  10.408 +	current->h = vinfo.h;
  10.409 +	current->pitch = SDL_CalculatePitch(current);
  10.410 +
  10.411 +	/* Memory map the DMA area for block memory transfer */
  10.412 +	if ( ! mapped_mem ) {
  10.413 +		pixels_len = height * current->pitch;
  10.414 +		mapped_len = pixels_len +
  10.415 +		             /* Screen update DMA command area */
  10.416 +		             sizeof(head_tags) + ((2 * MAXTAGS) * 16);
  10.417 +		mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE,
  10.418 +		                  MAP_SHARED, memory_fd, 0);
  10.419 +		if ( mapped_mem == MAP_FAILED ) {
  10.420 +			SDL_SetError("Unable to map %d bytes for DMA",
  10.421 +			             mapped_len);
  10.422 +			mapped_mem = NULL;
  10.423 +			return(NULL);
  10.424 +		}
  10.425 +
  10.426 +		/* Set up the entire screen for DMA transfer */
  10.427 +		screen_image.ptr = mapped_mem;
  10.428 +		screen_image.fbp = 0;
  10.429 +		screen_image.fbw = (vinfo.w + 63) / 64;
  10.430 +		screen_image.psm = vinfo.psm;
  10.431 +		screen_image.x = 0;
  10.432 +		screen_image.y = 0;
  10.433 +		screen_image.w = vinfo.w;
  10.434 +		screen_image.h = vinfo.h;
  10.435 +
  10.436 +		/* get screen image data size (qword aligned) */
  10.437 +		screen_image_size = (vinfo.w * vinfo.h);
  10.438 +		switch (screen_image.psm) {
  10.439 +		    case PS2_GS_PSMCT32:
  10.440 +			screen_image_size *= 4;
  10.441 +			break;
  10.442 +		    case PS2_GS_PSMCT24:
  10.443 +			screen_image_size *= 3;
  10.444 +			break;
  10.445 +		    case PS2_GS_PSMCT16:
  10.446 +			screen_image_size *= 2;
  10.447 +			break;
  10.448 +		}
  10.449 +		screen_image_size = (screen_image_size + 15) & ~15;
  10.450 +
  10.451 +		/* Set up the memory for screen update DMA commands */
  10.452 +		head_tags_mem = (unsigned long long *)
  10.453 +		                (mapped_mem + pixels_len);
  10.454 +		image_tags_mem = (unsigned long long *)
  10.455 +		                 ((caddr_t)head_tags_mem + sizeof(head_tags));
  10.456 +		memcpy(head_tags_mem, head_tags, sizeof(head_tags));
  10.457 +	}
  10.458 +	current->pixels = NULL;
  10.459 +	if ( getenv("SDL_FULLSCREEN_UPDATE") ) {
  10.460 +		/* Correct semantics */
  10.461 +		current->flags |= SDL_ASYNCBLIT;
  10.462 +	} else {
  10.463 +		/* We lie here - the screen memory isn't really the visible
  10.464 +		   display memory and still requires an update, but this
  10.465 +		   has the desired effect for most applications.
  10.466 +		 */
  10.467 +		current->flags |= SDL_HWSURFACE;
  10.468 +	}
  10.469 +
  10.470 +	/* Set the update rectangle function */
  10.471 +	this->UpdateRects = GS_DMAFullUpdate;
  10.472 +
  10.473 +	/* We're done */
  10.474 +	return(current);
  10.475 +}
  10.476 +
  10.477 +/* We don't support hardware surfaces yet */
  10.478 +static int GS_AllocHWSurface(_THIS, SDL_Surface *surface)
  10.479 +{
  10.480 +	return(-1);
  10.481 +}
  10.482 +static void GS_FreeHWSurface(_THIS, SDL_Surface *surface)
  10.483 +{
  10.484 +	return;
  10.485 +}
  10.486 +static int GS_LockHWSurface(_THIS, SDL_Surface *surface)
  10.487 +{
  10.488 +	if ( surface == this->screen ) {
  10.489 +		/* Since mouse motion affects 'pixels', lock it */
  10.490 +		SDL_LockCursor();
  10.491 +
  10.492 +		/* Make sure any pending DMA has completed */
  10.493 +		if ( dma_pending ) {
  10.494 +			ioctl(console_fd, PS2IOC_SENDQCT, 1);
  10.495 +			dma_pending = 0;
  10.496 +		}
  10.497 +
  10.498 +		/* If the cursor is drawn on the DMA area, remove it */
  10.499 +		if ( cursor_drawn ) {
  10.500 +			surface->pixels = mapped_mem + surface->offset;
  10.501 +			SDL_EraseCursorNoLock(this->screen);
  10.502 +			cursor_drawn = 0;
  10.503 +		}
  10.504 +
  10.505 +		/* Set the surface pixels to the base of the DMA area */
  10.506 +		surface->pixels = mapped_mem;
  10.507 +
  10.508 +		/* We're finished! */
  10.509 +		SDL_UnlockCursor();
  10.510 +	}
  10.511 +	return(0);
  10.512 +}
  10.513 +static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface)
  10.514 +{
  10.515 +	if ( surface == this->screen ) {
  10.516 +		/* Since mouse motion affects 'pixels', lock it */
  10.517 +		SDL_LockCursor();
  10.518 +		surface->pixels = NULL;
  10.519 +		SDL_UnlockCursor();
  10.520 +	}
  10.521 +}
  10.522 +
  10.523 +static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects)
  10.524 +{
  10.525 +	/* Lock so we aren't interrupted by a mouse update */
  10.526 +	SDL_LockCursor();
  10.527 +
  10.528 +	/* Make sure any pending DMA has completed */
  10.529 +	if ( dma_pending ) {
  10.530 +		ioctl(console_fd, PS2IOC_SENDQCT, 1);
  10.531 +		dma_pending = 0;
  10.532 +	}
  10.533 +
  10.534 +	/* If the mouse is visible, draw it on the DMA area */
  10.535 +	if ( (SDL_cursorstate & CURSOR_VISIBLE) && !cursor_drawn ) {
  10.536 +		this->screen->pixels = mapped_mem + this->screen->offset;
  10.537 +		SDL_DrawCursorNoLock(this->screen);
  10.538 +		this->screen->pixels = NULL;
  10.539 +		cursor_drawn = 1;
  10.540 +	}
  10.541 +
  10.542 +	/* Put the image onto the screen */
  10.543 +	loadimage_nonblock(console_fd,
  10.544 +	                   &screen_image, screen_image_size,
  10.545 +	                   head_tags_mem, image_tags_mem);
  10.546 +	dma_pending = 1;
  10.547 +
  10.548 +	/* We're finished! */
  10.549 +	SDL_UnlockCursor();
  10.550 +}
  10.551 +
  10.552 +static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  10.553 +{
  10.554 +	return(0);
  10.555 +}
  10.556 +
  10.557 +static void GS_VideoQuit(_THIS)
  10.558 +{
  10.559 +	/* Close console and input file descriptors */
  10.560 +	if ( console_fd > 0 ) {
  10.561 +		/* Unmap the video framebuffer */
  10.562 +		if ( mapped_mem ) {
  10.563 +			/* Unmap the video framebuffer */
  10.564 +			munmap(mapped_mem, mapped_len);
  10.565 +			mapped_mem = NULL;
  10.566 +		}
  10.567 +		close(memory_fd);
  10.568 +
  10.569 +		/* Restore the original video mode */
  10.570 +		if ( GS_InGraphicsMode(this) ) {
  10.571 +			ioctl(console_fd, PS2IOC_SSCREENINFO, &saved_vinfo);
  10.572 +		}
  10.573 +
  10.574 +		/* We're all done with the graphics device */
  10.575 +		close(console_fd);
  10.576 +		console_fd = -1;
  10.577 +	}
  10.578 +	GS_CloseMouse(this);
  10.579 +	GS_CloseKeyboard(this);
  10.580 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/video/ps2gs/SDL_gsvideo.h	Sat Jun 16 03:17:45 2001 +0000
    11.3 @@ -0,0 +1,92 @@
    11.4 +/*
    11.5 +    SDL - Simple DirectMedia Layer
    11.6 +    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
    11.7 +
    11.8 +    This library is free software; you can redistribute it and/or
    11.9 +    modify it under the terms of the GNU Library General Public
   11.10 +    License as published by the Free Software Foundation; either
   11.11 +    version 2 of the License, or (at your option) any later version.
   11.12 +
   11.13 +    This library is distributed in the hope that it will be useful,
   11.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   11.16 +    Library General Public License for more details.
   11.17 +
   11.18 +    You should have received a copy of the GNU Library General Public
   11.19 +    License along with this library; if not, write to the Free
   11.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   11.21 +
   11.22 +    Sam Lantinga
   11.23 +    slouken@devolution.com
   11.24 +*/
   11.25 +
   11.26 +#ifdef SAVE_RCSID
   11.27 +static char rcsid =
   11.28 + "@(#) $Id$";
   11.29 +#endif
   11.30 +
   11.31 +#ifndef _SDL_gsvideo_h
   11.32 +#define _SDL_gsvideo_h
   11.33 +
   11.34 +#include <sys/types.h>
   11.35 +#include <termios.h>
   11.36 +#include <linux/ps2/dev.h>
   11.37 +#include <linux/ps2/gs.h>
   11.38 +
   11.39 +#include "SDL_mouse.h"
   11.40 +#include "SDL_mutex.h"
   11.41 +#include "SDL_sysvideo.h"
   11.42 +
   11.43 +/* Hidden "this" pointer for the video functions */
   11.44 +#define _THIS	SDL_VideoDevice *this
   11.45 +
   11.46 +
   11.47 +/* Private display data */
   11.48 +struct SDL_PrivateVideoData {
   11.49 +	/* Gotta love that simple PS2 graphics interface. :) */
   11.50 +	int console_fd;
   11.51 +	int memory_fd;
   11.52 +	struct ps2_screeninfo saved_vinfo;
   11.53 +
   11.54 +	/* Ye olde linux keyboard code */
   11.55 +	int current_vt;
   11.56 +	int saved_vt;
   11.57 +	int keyboard_fd;
   11.58 +	int saved_kbd_mode;
   11.59 +	struct termios saved_kbd_termios;
   11.60 +
   11.61 +	/* Ye olde linux mouse code */
   11.62 +	int mouse_fd;
   11.63 +	int cursor_drawn;
   11.64 +
   11.65 +	/* The memory mapped DMA area and associated variables */
   11.66 +	caddr_t mapped_mem;
   11.67 +	int pixels_len;
   11.68 +	int mapped_len;
   11.69 +	struct ps2_image screen_image;
   11.70 +	int screen_image_size;
   11.71 +	unsigned long long *head_tags_mem;
   11.72 +	unsigned long long *image_tags_mem;
   11.73 +	int dma_pending;
   11.74 +};
   11.75 +/* Old variable names */
   11.76 +#define console_fd		(this->hidden->console_fd)
   11.77 +#define memory_fd		(this->hidden->memory_fd)
   11.78 +#define saved_vinfo		(this->hidden->saved_vinfo)
   11.79 +#define current_vt		(this->hidden->current_vt)
   11.80 +#define saved_vt		(this->hidden->saved_vt)
   11.81 +#define keyboard_fd		(this->hidden->keyboard_fd)
   11.82 +#define saved_kbd_mode		(this->hidden->saved_kbd_mode)
   11.83 +#define saved_kbd_termios	(this->hidden->saved_kbd_termios)
   11.84 +#define mouse_fd		(this->hidden->mouse_fd)
   11.85 +#define cursor_drawn		(this->hidden->cursor_drawn)
   11.86 +#define mapped_mem		(this->hidden->mapped_mem)
   11.87 +#define pixels_len		(this->hidden->pixels_len)
   11.88 +#define mapped_len		(this->hidden->mapped_len)
   11.89 +#define screen_image		(this->hidden->screen_image)
   11.90 +#define screen_image_size	(this->hidden->screen_image_size)
   11.91 +#define head_tags_mem		(this->hidden->head_tags_mem)
   11.92 +#define image_tags_mem		(this->hidden->image_tags_mem)
   11.93 +#define dma_pending		(this->hidden->dma_pending)
   11.94 +
   11.95 +#endif /* _SDL_gsvideo_h */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/video/ps2gs/SDL_gsyuv.c	Sat Jun 16 03:17:45 2001 +0000
    12.3 @@ -0,0 +1,467 @@
    12.4 +/*
    12.5 +    SDL - Simple DirectMedia Layer
    12.6 +    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
    12.7 +
    12.8 +    This library is free software; you can redistribute it and/or
    12.9 +    modify it under the terms of the GNU Library General Public
   12.10 +    License as published by the Free Software Foundation; either
   12.11 +    version 2 of the License, or (at your option) any later version.
   12.12 +
   12.13 +    This library is distributed in the hope that it will be useful,
   12.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12.16 +    Library General Public License for more details.
   12.17 +
   12.18 +    You should have received a copy of the GNU Library General Public
   12.19 +    License along with this library; if not, write to the Free
   12.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   12.21 +
   12.22 +    Sam Lantinga
   12.23 +    slouken@devolution.com
   12.24 +*/
   12.25 +
   12.26 +#ifdef SAVE_RCSID
   12.27 +static char rcsid =
   12.28 + "@(#) $Id$";
   12.29 +#endif
   12.30 +
   12.31 +/* This is the Playstation 2 implementation of YUV video overlays */
   12.32 +
   12.33 +#include <stdlib.h>
   12.34 +#include <string.h>
   12.35 +#include <fcntl.h>
   12.36 +#include <unistd.h>
   12.37 +#include <sys/ioctl.h>
   12.38 +#include <sys/mman.h>
   12.39 +#include <asm/page.h>		/* For definition of PAGE_SIZE */
   12.40 +
   12.41 +#include "SDL_error.h"
   12.42 +#include "SDL_video.h"
   12.43 +#include "SDL_gsyuv_c.h"
   12.44 +#include "SDL_yuvfuncs.h"
   12.45 +
   12.46 +/* The maximum number of 16x16 pixel block converted at once */
   12.47 +#define MAX_MACROBLOCKS	1024	/* 2^10 macroblocks at once */
   12.48 +
   12.49 +/* The functions used to manipulate video overlays */
   12.50 +static struct private_yuvhwfuncs gs_yuvfuncs = {
   12.51 +	GS_LockYUVOverlay,
   12.52 +	GS_UnlockYUVOverlay,
   12.53 +	GS_DisplayYUVOverlay,
   12.54 +	GS_FreeYUVOverlay
   12.55 +};
   12.56 +
   12.57 +struct private_yuvhwdata {
   12.58 +	int ipu_fd;
   12.59 +	Uint8 *pixels;
   12.60 +	int macroblocks;
   12.61 +	int dma_len;
   12.62 +	caddr_t dma_mem;
   12.63 +	caddr_t ipu_imem;
   12.64 +	caddr_t ipu_omem;
   12.65 +	caddr_t dma_tags;
   12.66 +	unsigned long long *stretch_x1y1;
   12.67 +	unsigned long long *stretch_x2y2;
   12.68 +	struct ps2_plist plist;
   12.69 +
   12.70 +	/* These are just so we don't have to allocate them separately */
   12.71 +	Uint16 pitches[3];
   12.72 +	Uint8 *planes[3];
   12.73 +};
   12.74 +
   12.75 +static int power_of_2(int value)
   12.76 +{
   12.77 +	int shift;
   12.78 +
   12.79 +	for ( shift = 0; (1<<shift) < value; ++shift ) {
   12.80 +		/* Keep looking */ ;
   12.81 +	}
   12.82 +	return(shift);
   12.83 +}
   12.84 +
   12.85 +SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
   12.86 +{
   12.87 +	SDL_Overlay *overlay;
   12.88 +	struct private_yuvhwdata *hwdata;
   12.89 +	int map_offset;
   12.90 +	unsigned long long *tags;
   12.91 +	caddr_t base;
   12.92 +	int bpp;
   12.93 +	int fbp, fbw, psm;
   12.94 +	int x, y, w, h;
   12.95 +	int pnum;
   12.96 +	struct ps2_packet *packet;
   12.97 +	struct ps2_packet tex_packet;
   12.98 +
   12.99 +	/* We can only decode blocks of 16x16 pixels */
  12.100 +	if ( (width & 15) || (height & 15) ) {
  12.101 +		SDL_SetError("Overlay width/height must be multiples of 16");
  12.102 +		return(NULL);
  12.103 +	}
  12.104 +	/* Make sure the image isn't too large for a single DMA transfer */
  12.105 +	if ( ((width/16) * (height/16)) > MAX_MACROBLOCKS ) {
  12.106 +		SDL_SetError("Overlay too large (maximum size: %d pixels)",
  12.107 +		             MAX_MACROBLOCKS * 16 * 16);
  12.108 +		return(NULL);
  12.109 +	}
  12.110 +
  12.111 +	/* Double-check the requested format.  For simplicity, we'll only
  12.112 +	   support planar YUV formats.
  12.113 +	 */
  12.114 +	switch (format) {
  12.115 +	    case SDL_YV12_OVERLAY:
  12.116 +	    case SDL_IYUV_OVERLAY:
  12.117 +		/* Supported planar YUV format */
  12.118 +		break;
  12.119 +	    default:
  12.120 +		SDL_SetError("Unsupported YUV format");
  12.121 +		return(NULL);
  12.122 +	}
  12.123 +
  12.124 +	/* Create the overlay structure */
  12.125 +	overlay = (SDL_Overlay *)malloc(sizeof *overlay);
  12.126 +	if ( overlay == NULL ) {
  12.127 +		SDL_OutOfMemory();
  12.128 +		return(NULL);
  12.129 +	}
  12.130 +	memset(overlay, 0, (sizeof *overlay));
  12.131 +
  12.132 +	/* Fill in the basic members */
  12.133 +	overlay->format = format;
  12.134 +	overlay->w = width;
  12.135 +	overlay->h = height;
  12.136 +
  12.137 +	/* Set up the YUV surface function structure */
  12.138 +	overlay->hwfuncs = &gs_yuvfuncs;
  12.139 +	overlay->hw_overlay = 1;
  12.140 +
  12.141 +	/* Create the pixel data */
  12.142 +	hwdata = (struct private_yuvhwdata *)malloc(sizeof *hwdata);
  12.143 +	overlay->hwdata = hwdata;
  12.144 +	if ( hwdata == NULL ) {
  12.145 +		SDL_FreeYUVOverlay(overlay);
  12.146 +		SDL_OutOfMemory();
  12.147 +		return(NULL);
  12.148 +	}
  12.149 +	hwdata->ipu_fd = -1;
  12.150 +	hwdata->pixels = (Uint8 *)malloc(width*height*2);
  12.151 +	if ( hwdata->pixels == NULL ) {
  12.152 +		SDL_FreeYUVOverlay(overlay);
  12.153 +		SDL_OutOfMemory();
  12.154 +		return(NULL);
  12.155 +	}
  12.156 +	hwdata->macroblocks = (width/16) * (height/16);
  12.157 +
  12.158 +	/* Find the pitch and offset values for the overlay */
  12.159 +	overlay->pitches = hwdata->pitches;
  12.160 +	overlay->pixels = hwdata->planes;
  12.161 +	switch (format) {
  12.162 +	    case SDL_YV12_OVERLAY:
  12.163 +	    case SDL_IYUV_OVERLAY:
  12.164 +		overlay->pitches[0] = overlay->w;
  12.165 +		overlay->pitches[1] = overlay->pitches[0] / 2;
  12.166 +		overlay->pitches[2] = overlay->pitches[0] / 2;
  12.167 +	        overlay->pixels[0] = hwdata->pixels;
  12.168 +	        overlay->pixels[1] = overlay->pixels[0] +
  12.169 +		                     overlay->pitches[0] * overlay->h;
  12.170 +	        overlay->pixels[2] = overlay->pixels[1] +
  12.171 +		                     overlay->pitches[1] * overlay->h / 2;
  12.172 +		overlay->planes = 3;
  12.173 +		break;
  12.174 +	    default:
  12.175 +		/* We should never get here (caught above) */
  12.176 +		break;
  12.177 +	}
  12.178 +
  12.179 +	/* Theoretically we could support several concurrent decode
  12.180 +	   streams queueing up on the same file descriptor, but for
  12.181 +	   simplicity we'll support only one.  Opening the IPU more
  12.182 +	   than once will fail with EBUSY.
  12.183 +	*/
  12.184 +	hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR);
  12.185 +	if ( hwdata->ipu_fd < 0 ) {
  12.186 +		SDL_FreeYUVOverlay(overlay);
  12.187 +		SDL_SetError("Playstation 2 IPU busy");
  12.188 +		return(NULL);
  12.189 +	}
  12.190 +
  12.191 +	/* Allocate a DMA area for pixel conversion */
  12.192 +	bpp = this->screen->format->BytesPerPixel;
  12.193 +	map_offset = (mapped_len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
  12.194 +	hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) +
  12.195 +	                  width * height * bpp +
  12.196 +	                  hwdata->macroblocks * (16 * sizeof(long long)) +
  12.197 +	                  12 * sizeof(long long);
  12.198 +	hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ|PROT_WRITE,
  12.199 +	                       MAP_SHARED, memory_fd, map_offset);
  12.200 +	if ( hwdata->dma_mem == MAP_FAILED ) {
  12.201 +		hwdata->ipu_imem = (caddr_t)0;
  12.202 +		SDL_FreeYUVOverlay(overlay);
  12.203 +		SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len);
  12.204 +		return(NULL);
  12.205 +	}
  12.206 +	hwdata->ipu_imem = hwdata->dma_mem;
  12.207 +	hwdata->ipu_omem = hwdata->ipu_imem +
  12.208 +	                   hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
  12.209 +	hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp;
  12.210 +
  12.211 +	/* Allocate memory for the DMA packets */
  12.212 +	hwdata->plist.num = hwdata->macroblocks * 4 + 1;
  12.213 +	hwdata->plist.packet = (struct ps2_packet *)malloc(
  12.214 +	                       hwdata->plist.num*sizeof(struct ps2_packet));
  12.215 +	if ( ! hwdata->plist.packet ) {
  12.216 +		SDL_FreeYUVOverlay(overlay);
  12.217 +		SDL_OutOfMemory();
  12.218 +		return(NULL);
  12.219 +	}
  12.220 +	pnum = 0;
  12.221 +	packet = hwdata->plist.packet;
  12.222 +
  12.223 +	/* Set up the tags to send the image to the screen */
  12.224 +	tags = (unsigned long long *)hwdata->dma_tags;
  12.225 +	base = hwdata->ipu_omem;
  12.226 +	fbp = screen_image.fbp;
  12.227 +	fbw = screen_image.fbw;
  12.228 +	psm = screen_image.psm;
  12.229 +	y = screen_image.h;	/* Offscreen video memory */
  12.230 +	for ( h=height/16; h; --h ) {
  12.231 +		x = 0;			/* Visible video memory */
  12.232 +		for ( w=width/16; w; --w ) {
  12.233 +			/* The head tag */
  12.234 +			packet[pnum].ptr = &tags[0];
  12.235 +			packet[pnum].len = 10 * sizeof(*tags);
  12.236 +			++pnum;
  12.237 +			tags[0] = 4 | (1LL << 60);	/* GIFtag */
  12.238 +			tags[1] = 0x0e;			/* A+D */
  12.239 +			tags[2] = ((unsigned long long)fbp << 32) |
  12.240 +			          ((unsigned long long)fbw << 48) |
  12.241 +			          ((unsigned long long)psm << 56);
  12.242 +			tags[3] = PS2_GS_BITBLTBUF;
  12.243 +			tags[4] = ((unsigned long long)x << 32) |
  12.244 +			          ((unsigned long long)y << 48);
  12.245 +			tags[5] = PS2_GS_TRXPOS;
  12.246 +			tags[6] = (unsigned long long)16 |
  12.247 +			          ((unsigned long long)16 << 32);
  12.248 +			tags[7] = PS2_GS_TRXREG;
  12.249 +			tags[8] = 0;
  12.250 +			tags[9] = PS2_GS_TRXDIR;
  12.251 +			/* Now the actual image data */
  12.252 +			packet[pnum].ptr = &tags[10];
  12.253 +			packet[pnum].len = 2 * sizeof(*tags);
  12.254 +			++pnum;
  12.255 +			tags[10] = ((16*16*bpp) >> 4) | (2LL << 58);
  12.256 +			tags[11] = 0;
  12.257 +			packet[pnum].ptr = (void *)base;
  12.258 +			packet[pnum].len = 16 * 16 * bpp;
  12.259 +			++pnum;
  12.260 +			packet[pnum].ptr = &tags[12];
  12.261 +			packet[pnum].len = 2 * sizeof(*tags);
  12.262 +			++pnum;
  12.263 +			tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58);
  12.264 +			tags[13] = 0;
  12.265 +
  12.266 +			tags += 16;
  12.267 +			base += 16 * 16 * bpp;
  12.268 +
  12.269 +			x += 16;
  12.270 +		}
  12.271 +		y += 16;
  12.272 +	}
  12.273 +
  12.274 +	/* Set up the texture memory area for the video */
  12.275 +	tex_packet.ptr = tags;
  12.276 +	tex_packet.len = 8 * sizeof(*tags);
  12.277 +	tags[0] = 3 | (1LL << 60);	/* GIFtag */
  12.278 +	tags[1] = 0x0e;			/* A+D */
  12.279 +	tags[2] = (screen_image.h * screen_image.w) / 64 +
  12.280 +	          ((unsigned long long)fbw << 14) +
  12.281 +	          ((unsigned long long)psm << 20) +
  12.282 +	          ((unsigned long long)power_of_2(width) << 26) +
  12.283 +	          ((unsigned long long)power_of_2(height) << 30) +
  12.284 +	          ((unsigned long long)1 << 34) +
  12.285 +	          ((unsigned long long)1 << 35);
  12.286 +	tags[3] = PS2_GS_TEX0_1;
  12.287 +	tags[4] = (1 << 5) + (1 << 6);
  12.288 +	tags[5] = PS2_GS_TEX1_1;
  12.289 +	tags[6] = 0;
  12.290 +	tags[7] = PS2_GS_TEXFLUSH;
  12.291 +	ioctl(console_fd, PS2IOC_SEND, &tex_packet);
  12.292 +
  12.293 +	/* Set up the tags for scaling the image */
  12.294 +	packet[pnum].ptr = tags;
  12.295 +	packet[pnum].len = 12 * sizeof(*tags);
  12.296 +	++pnum;
  12.297 +	tags[0] = 5 | (1LL << 60);	/* GIFtag */
  12.298 +	tags[1] = 0x0e;			/* A+D */
  12.299 +	tags[2] = 6 + (1 << 4) + (1 << 8);
  12.300 +	tags[3] = PS2_GS_PRIM;
  12.301 +	tags[4] = ((unsigned long long)0 * 16) +
  12.302 +	           (((unsigned long long)0 * 16) << 16);
  12.303 +	tags[5] = PS2_GS_UV;
  12.304 +	tags[6] = 0; /* X1, Y1 */
  12.305 +	tags[7] = PS2_GS_XYZ2;
  12.306 +	hwdata->stretch_x1y1 = &tags[6];
  12.307 +	tags[8] = ((unsigned long long)overlay->w * 16) +
  12.308 +	           (((unsigned long long)overlay->h * 16) << 16);
  12.309 +	tags[9] = PS2_GS_UV;
  12.310 +	tags[10] = 0; /* X2, Y2 */
  12.311 +	tags[11] = PS2_GS_XYZ2;
  12.312 +	hwdata->stretch_x2y2 = &tags[10];
  12.313 +
  12.314 +	/* We're all done.. */
  12.315 +	return(overlay);
  12.316 +}
  12.317 +
  12.318 +int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay)
  12.319 +{
  12.320 +	return(0);
  12.321 +}
  12.322 +
  12.323 +void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay)
  12.324 +{
  12.325 +	return;
  12.326 +}
  12.327 +
  12.328 +int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
  12.329 +{
  12.330 +	struct private_yuvhwdata *hwdata;
  12.331 +	__u32 cmd;
  12.332 +	struct ps2_packet packet;
  12.333 +	int h, w, i;
  12.334 +	Uint32 *lum, *Cr, *Cb;
  12.335 +	int lum_pitch;
  12.336 +	int crb_pitch;
  12.337 +	Uint32 *lum_src, *Cr_src, *Cb_src;
  12.338 +	Uint32 *src, *dst;
  12.339 +	unsigned int x, y;
  12.340 +	SDL_Surface *screen;
  12.341 +
  12.342 +	/* Find out where the various portions of the image are */
  12.343 +	hwdata = overlay->hwdata;
  12.344 +	switch (overlay->format) {
  12.345 +	    case SDL_YV12_OVERLAY:
  12.346 +		lum = (Uint32 *)overlay->pixels[0];
  12.347 +		Cr =  (Uint32 *)overlay->pixels[1];
  12.348 +		Cb =  (Uint32 *)overlay->pixels[2];
  12.349 +		break;
  12.350 +	    case SDL_IYUV_OVERLAY:
  12.351 +		lum = (Uint32 *)overlay->pixels[0];
  12.352 +		Cr =  (Uint32 *)overlay->pixels[2];
  12.353 +		Cb =  (Uint32 *)overlay->pixels[1];
  12.354 +	    default:
  12.355 +		SDL_SetError("Unsupported YUV format in blit (??)");
  12.356 +		return(-1);
  12.357 +	}
  12.358 +	dst = (Uint32 *)hwdata->ipu_imem;
  12.359 +	lum_pitch = overlay->w/4;
  12.360 +	crb_pitch = (overlay->w/2)/4;
  12.361 +
  12.362 +	/* Copy blocks of 16x16 pixels to the DMA area */
  12.363 +	for ( h=overlay->h/16; h; --h ) {
  12.364 +		lum_src = lum;
  12.365 +		Cr_src = Cr;
  12.366 +		Cb_src = Cb;
  12.367 +		for ( w=overlay->w/16; w; --w ) {
  12.368 +			src = lum_src;
  12.369 +			for ( i=0; i<16; ++i ) {
  12.370 +				dst[0] = src[0];
  12.371 +				dst[1] = src[1];
  12.372 +				dst[2] = src[2];
  12.373 +				dst[3] = src[3];
  12.374 +				src += lum_pitch;
  12.375 +				dst += 4;
  12.376 +			}
  12.377 +			src = Cb_src;
  12.378 +			for ( i=0; i<8; ++i ) {
  12.379 +				dst[0] = src[0];
  12.380 +				dst[1] = src[1];
  12.381 +				src += crb_pitch;
  12.382 +				dst += 2;
  12.383 +			}
  12.384 +			src = Cr_src;
  12.385 +			for ( i=0; i<8; ++i ) {
  12.386 +				dst[0] = src[0];
  12.387 +				dst[1] = src[1];
  12.388 +				src += crb_pitch;
  12.389 +				dst += 2;
  12.390 +			}
  12.391 +			lum_src += 16 / 4;
  12.392 +			Cb_src += 8 / 4;
  12.393 +			Cr_src += 8 / 4;
  12.394 +		}
  12.395 +		lum += lum_pitch * 16;
  12.396 +		Cr += crb_pitch * 8;
  12.397 +		Cb += crb_pitch * 8;
  12.398 +	}
  12.399 +
  12.400 +	/* Send the macroblock data to the IPU */
  12.401 +#ifdef DEBUG_YUV
  12.402 +	fprintf(stderr, "Sending data to IPU..\n");
  12.403 +#endif
  12.404 +	packet.ptr = hwdata->ipu_imem;
  12.405 +	packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
  12.406 +	ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet);
  12.407 +
  12.408 +	/* Trigger the DMA to the IPU for conversion */
  12.409 +#ifdef DEBUG_YUV
  12.410 +	fprintf(stderr, "Trigging conversion command\n");
  12.411 +#endif
  12.412 +	cmd = (7 << 28) + hwdata->macroblocks;
  12.413 +	if ( screen_image.psm == PS2_GS_PSMCT16 ) {
  12.414 +		cmd += (1 << 27) +	/* Output RGB 555 */
  12.415 +		       (1 << 26);	/* Dither output */
  12.416 +	}
  12.417 +	ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd);
  12.418 +
  12.419 +	/* Retrieve the converted image from the IPU */
  12.420 +#ifdef DEBUG_YUV
  12.421 +	fprintf(stderr, "Retrieving data from IPU..\n");
  12.422 +#endif
  12.423 +	packet.ptr = hwdata->ipu_omem;
  12.424 +	packet.len = overlay->w * overlay->h *
  12.425 +	             this->screen->format->BytesPerPixel;
  12.426 +	ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet);
  12.427 +
  12.428 +#ifdef DEBUG_YUV
  12.429 +	fprintf(stderr, "Copying image to screen..\n");
  12.430 +#endif
  12.431 +	/* Wait for previous DMA to complete */
  12.432 +	ioctl(console_fd, PS2IOC_SENDQCT, 1);
  12.433 +
  12.434 +	/* Send the current image to the screen and scale it */
  12.435 +	screen = this->screen;
  12.436 +	x = (unsigned int)dstrect->x;
  12.437 +	y = (unsigned int)dstrect->y;
  12.438 +	if ( screen->offset ) {
  12.439 +		x += (screen->offset % screen->pitch) /
  12.440 +		     screen->format->BytesPerPixel;
  12.441 +		y += (screen->offset / screen->pitch);
  12.442 +	}
  12.443 +	*hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
  12.444 +	x += (unsigned int)dstrect->w;
  12.445 +	y += (unsigned int)dstrect->h;
  12.446 +	*hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16);
  12.447 +	return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist);
  12.448 +}
  12.449 +
  12.450 +void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
  12.451 +{
  12.452 +	struct private_yuvhwdata *hwdata;
  12.453 +
  12.454 +	hwdata = overlay->hwdata;
  12.455 +	if ( hwdata ) {
  12.456 +		if ( hwdata->ipu_fd >= 0 ) {
  12.457 +			close(hwdata->ipu_fd);
  12.458 +		}
  12.459 +		if ( hwdata->dma_mem ) {
  12.460 +			munmap(hwdata->dma_mem, hwdata->dma_len);
  12.461 +		}
  12.462 +		if ( hwdata->plist.packet ) {
  12.463 +			free(hwdata->plist.packet);
  12.464 +		}
  12.465 +		if ( hwdata->pixels ) {
  12.466 +			free(hwdata->pixels);
  12.467 +		}
  12.468 +		free(hwdata);
  12.469 +	}
  12.470 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/video/ps2gs/SDL_gsyuv_c.h	Sat Jun 16 03:17:45 2001 +0000
    13.3 @@ -0,0 +1,41 @@
    13.4 +/*
    13.5 +    SDL - Simple DirectMedia Layer
    13.6 +    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
    13.7 +
    13.8 +    This library is free software; you can redistribute it and/or
    13.9 +    modify it under the terms of the GNU Library General Public
   13.10 +    License as published by the Free Software Foundation; either
   13.11 +    version 2 of the License, or (at your option) any later version.
   13.12 +
   13.13 +    This library is distributed in the hope that it will be useful,
   13.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13.16 +    Library General Public License for more details.
   13.17 +
   13.18 +    You should have received a copy of the GNU Library General Public
   13.19 +    License along with this library; if not, write to the Free
   13.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   13.21 +
   13.22 +    Sam Lantinga
   13.23 +    slouken@devolution.com
   13.24 +*/
   13.25 +
   13.26 +#ifdef SAVE_RCSID
   13.27 +static char rcsid =
   13.28 + "@(#) $Id$";
   13.29 +#endif
   13.30 +
   13.31 +/* This is the Playstation 2 implementation of YUV video overlays */
   13.32 +
   13.33 +#include "SDL_video.h"
   13.34 +#include "SDL_gsvideo.h"
   13.35 +
   13.36 +extern SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display);
   13.37 +
   13.38 +extern int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay);
   13.39 +
   13.40 +extern void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay);
   13.41 +
   13.42 +extern int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect);
   13.43 +
   13.44 +extern void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay);