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