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