gnuboy-for-dfi/sys/sdl/sdl.c

559 lines
11 KiB
C

/*
* sdl.c
* sdl interfaces -- based on svga.c
*
* (C) 2001 Damian Gryski <dgryski@uwaterloo.ca>
* Joystick code contributed by David Lau
*
* Licensed under the GPLv2, or later.
*/
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
/* Von Stefan */
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFSIZE 5760
#define SERVICE_PORT 2323
#define FRAME_SKIP -1
/* Ende von Stefan */
#include "fb.h"
#include "input.h"
#include "rc.h"
/* By Stefan */
static struct sockaddr_in myaddr, remaddr;
static int fd, slen=sizeof(remaddr);
static char frame[BUFSIZE]; /* message buffer */
static char *server = "195.160.169.37"; /* change this to use a different server */
static int frameCount = 0;
/* End Stefan */
struct fb fb;
static int use_yuv = -1;
static int fullscreen = 0;
static int use_altenter = 1;
static int use_joy = 1, sdl_joy_num;
static SDL_Joystick * sdl_joy = NULL;
static const int joy_commit_range = 3276;
static char Xstatus, Ystatus;
static SDL_Surface *screen;
static SDL_Overlay *overlay;
static SDL_Rect overlay_rect;
static int vmode[3] = { 0, 0, 16 };
rcvar_t vid_exports[] =
{
RCV_VECTOR("vmode", &vmode, 3),
RCV_BOOL("yuv", &use_yuv),
RCV_BOOL("fullscreen", &fullscreen),
RCV_BOOL("altenter", &use_altenter),
RCV_END
};
rcvar_t joy_exports[] =
{
RCV_BOOL("joy", &use_joy),
RCV_END
};
/* keymap - mappings of the form { scancode, localcode } - from sdl/keymap.c */
extern int keymap[][2];
static int mapscancode(SDLKey sym)
{
/* this could be faster: */
/* build keymap as int keymap[256], then ``return keymap[sym]'' */
int i;
for (i = 0; keymap[i][0]; i++)
if (keymap[i][0] == sym)
return keymap[i][1];
if (sym >= '0' && sym <= '9')
return sym;
if (sym >= 'a' && sym <= 'z')
return sym;
return 0;
}
static void joy_init()
{
int i;
int joy_count;
/* Initilize the Joystick, and disable all later joystick code if an error occured */
if (!use_joy) return;
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK))
return;
joy_count = SDL_NumJoysticks();
if (!joy_count)
return;
/* now try and open one. If, for some reason it fails, move on to the next one */
for (i = 0; i < joy_count; i++)
{
sdl_joy = SDL_JoystickOpen(i);
if (sdl_joy)
{
sdl_joy_num = i;
break;
}
}
/* make sure that Joystick event polling is a go */
SDL_JoystickEventState(SDL_ENABLE);
}
static void overlay_init()
{
if (!use_yuv) return;
if (use_yuv < 0)
if (vmode[0] < 320 || vmode[1] < 288)
return;
overlay = SDL_CreateYUVOverlay(320, 144, SDL_YUY2_OVERLAY, screen);
if (!overlay) return;
if (!overlay->hw_overlay || overlay->planes > 1)
{
SDL_FreeYUVOverlay(overlay);
overlay = 0;
return;
}
SDL_LockYUVOverlay(overlay);
fb.w = 160;
fb.h = 144;
fb.pelsize = 4;
fb.pitch = overlay->pitches[0];
fb.ptr = overlay->pixels[0];
fb.yuv = 1;
fb.cc[0].r = fb.cc[1].r = fb.cc[2].r = fb.cc[3].r = 0;
fb.dirty = 1;
fb.enabled = 1;
overlay_rect.x = 0;
overlay_rect.y = 0;
overlay_rect.w = vmode[0];
overlay_rect.h = vmode[1];
/* Color channels are 0=Y, 1=U, 2=V, 3=Y1 */
switch (overlay->format)
{
/* FIXME - support more formats */
case SDL_YUY2_OVERLAY:
default:
fb.cc[0].l = 0;
fb.cc[1].l = 24;
fb.cc[2].l = 8;
fb.cc[3].l = 16;
break;
}
SDL_UnlockYUVOverlay(overlay);
}
void vid_init()
{
int flags;
if (!vmode[0] || !vmode[1])
{
int scale = rc_getint("scale");
if (scale < 1) scale = 1;
vmode[0] = 160 * scale;
vmode[1] = 144 * scale;
}
flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE;
if (fullscreen)
flags |= SDL_FULLSCREEN;
if (SDL_Init(SDL_INIT_VIDEO))
die("SDL: Couldn't initialize SDL: %s\n", SDL_GetError());
if (!(screen = SDL_SetVideoMode(vmode[0], vmode[1], vmode[2], flags)))
die("SDL: can't set video mode: %s\n", SDL_GetError());
SDL_ShowCursor(0);
joy_init();
overlay_init();
if (fb.yuv) return;
SDL_LockSurface(screen);
fb.w = screen->w;
fb.h = screen->h;
fb.pelsize = screen->format->BytesPerPixel;
fb.pitch = screen->pitch;
fb.indexed = fb.pelsize == 1;
fb.ptr = screen->pixels;
fb.cc[0].r = screen->format->Rloss;
fb.cc[0].l = screen->format->Rshift;
fb.cc[1].r = screen->format->Gloss;
fb.cc[1].l = screen->format->Gshift;
fb.cc[2].r = screen->format->Bloss;
fb.cc[2].l = screen->format->Bshift;
SDL_UnlockSurface(screen);
fb.enabled = 1;
fb.dirty = 0;
/* Start Init Stefan */
/* create a socket */
printf("Start Init\n");
if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1)
printf("socket created\n");
/* bind it to all local addresses and pick any port number */
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
die("bind failed");
}
/* now define remaddr, the address to whom we want to send messages */
/* For convenience, the host address is expressed as a numeric IP address */
/* that we will convert to a binary format via inet_aton */
memset((char *) &remaddr, 0, sizeof(remaddr));
remaddr.sin_family = AF_INET;
remaddr.sin_port = htons(SERVICE_PORT);
if (inet_aton(server, &remaddr.sin_addr)==0) {
fprintf(stderr, "inet_aton() failed\n");
die("1");
}
printf("End Init\n");
/* Ende Stefan */
}
void ev_poll()
{
event_t ev;
SDL_Event event;
int axisval;
while (SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_ACTIVEEVENT:
if (event.active.state == SDL_APPACTIVE)
fb.enabled = event.active.gain;
break;
case SDL_KEYDOWN:
if ((event.key.keysym.sym == SDLK_RETURN) && (event.key.keysym.mod & KMOD_ALT))
SDL_WM_ToggleFullScreen(screen);
ev.type = EV_PRESS;
ev.code = mapscancode(event.key.keysym.sym);
ev_postevent(&ev);
break;
case SDL_KEYUP:
ev.type = EV_RELEASE;
ev.code = mapscancode(event.key.keysym.sym);
ev_postevent(&ev);
break;
case SDL_JOYAXISMOTION:
switch (event.jaxis.axis)
{
case 0: /* X axis */
axisval = event.jaxis.value;
if (axisval > joy_commit_range)
{
if (Xstatus==2) break;
if (Xstatus==0)
{
ev.type = EV_RELEASE;
ev.code = K_JOYLEFT;
ev_postevent(&ev);
}
ev.type = EV_PRESS;
ev.code = K_JOYRIGHT;
ev_postevent(&ev);
Xstatus=2;
break;
}
if (axisval < -(joy_commit_range))
{
if (Xstatus==0) break;
if (Xstatus==2)
{
ev.type = EV_RELEASE;
ev.code = K_JOYRIGHT;
ev_postevent(&ev);
}
ev.type = EV_PRESS;
ev.code = K_JOYLEFT;
ev_postevent(&ev);
Xstatus=0;
break;
}
/* if control reaches here, the axis is centered,
* so just send a release signal if necisary */
if (Xstatus==2)
{
ev.type = EV_RELEASE;
ev.code = K_JOYRIGHT;
ev_postevent(&ev);
}
if (Xstatus==0)
{
ev.type = EV_RELEASE;
ev.code = K_JOYLEFT;
ev_postevent(&ev);
}
Xstatus=1;
break;
case 1: /* Y axis*/
axisval = event.jaxis.value;
if (axisval > joy_commit_range)
{
if (Ystatus==2) break;
if (Ystatus==0)
{
ev.type = EV_RELEASE;
ev.code = K_JOYUP;
ev_postevent(&ev);
}
ev.type = EV_PRESS;
ev.code = K_JOYDOWN;
ev_postevent(&ev);
Ystatus=2;
break;
}
if (axisval < -joy_commit_range)
{
if (Ystatus==0) break;
if (Ystatus==2)
{
ev.type = EV_RELEASE;
ev.code = K_JOYDOWN;
ev_postevent(&ev);
}
ev.type = EV_PRESS;
ev.code = K_JOYUP;
ev_postevent(&ev);
Ystatus=0;
break;
}
/* if control reaches here, the axis is centered,
* so just send a release signal if necisary */
if (Ystatus==2)
{
ev.type = EV_RELEASE;
ev.code = K_JOYDOWN;
ev_postevent(&ev);
}
if (Ystatus==0)
{
ev.type = EV_RELEASE;
ev.code = K_JOYUP;
ev_postevent(&ev);
}
Ystatus=1;
break;
}
break;
case SDL_JOYBUTTONUP:
if (event.jbutton.button>15) break;
ev.type = EV_RELEASE;
ev.code = K_JOY0 + event.jbutton.button;
ev_postevent(&ev);
break;
case SDL_JOYBUTTONDOWN:
if (event.jbutton.button>15) break;
ev.type = EV_PRESS;
ev.code = K_JOY0+event.jbutton.button;
ev_postevent(&ev);
break;
case SDL_QUIT:
exit(1);
break;
default:
break;
}
}
}
void vid_setpal(int i, int r, int g, int b)
{
SDL_Color col;
col.r = r; col.g = g; col.b = b;
SDL_SetColors(screen, &col, i, 1);
}
void vid_preinit()
{
}
void vid_close()
{
if (overlay)
{
SDL_UnlockYUVOverlay(overlay);
SDL_FreeYUVOverlay(overlay);
}
else SDL_UnlockSurface(screen);
SDL_Quit();
fb.enabled = 0;
}
void vid_settitle(char *title)
{
SDL_WM_SetCaption(title, title);
}
void vid_begin()
{
int x;
char y;
if (overlay)
{
SDL_LockYUVOverlay(overlay);
fb.ptr = overlay->pixels[0];
return;
}
SDL_LockSurface(screen);
fb.ptr = screen->pixels;
frameCount++;
if (frameCount % FRAME_SKIP) {
return;
}
/* Stefan Start - Sending Frame via UDP to DFI*/
/* Geht so halb...
for(x=0; x<144*40; x++){
if(fb.ptr[x*16]==29) frame[x]=0;
if(fb.ptr[x*16]==99) frame[x]=1;
if(fb.ptr[x*16]==107) frame[x]=2;
if(fb.ptr[x*16]==156) frame[x]=3;
if(fb.ptr[(x*16)+4]==29) frame[x]+=0;
if(fb.ptr[(x*16)+4]==99) frame[x]+=4;
if(fb.ptr[(x*16)+4]==107) frame[x]+=8;
if(fb.ptr[(x*16)+4]==156) frame[x]+=12;
if(fb.ptr[(x*16)+8]==29) frame[x]+=0;
if(fb.ptr[(x*16)+8]==99) frame[x]+=16;
if(fb.ptr[(x*16)+8]==107) frame[x]+=32;
if(fb.ptr[(x*16)+8]==156) frame[x]+=48;
if(fb.ptr[(x*16)+12]==29) frame[x]+=0;
if(fb.ptr[(x*16)+12]==99) frame[x]+=64;
if(fb.ptr[(x*16)+12]==107) frame[x]+=128;
if(fb.ptr[(x*16)+12]==156) frame[x]+=192;
} */
int displaySize = 144*160;
for(x=0; x<displaySize; x++){
int color = fb.ptr[x*4];
if (color == 41) {
y=0;
} else if (color == 99) {
y=1;
} else if (color <= 107) {
y=2;
} else if (color <= 156) {
y=3;
} else {
y=0;
}
int pixelModulo = x %4;
if (pixelModulo == 0) {
frame[x/4] =y;
} else if (pixelModulo == 1) {
frame[x/4]+=(y<<2);
} else if (pixelModulo == 2) {
frame[x/4]+=(y<<4);
} else if (pixelModulo == 3) {
frame[x/4]+=(y<<6);
}
}
if (sendto(fd, frame, BUFSIZE, 0, (struct sockaddr *)&remaddr, slen)==-1) {
printf("error sending frame\n");
}
/*printf("send; %d\n",frameCount);*/
/* Stefan Ende */
}
void vid_end()
{
if (overlay)
{
SDL_UnlockYUVOverlay(overlay);
if (fb.enabled)
SDL_DisplayYUVOverlay(overlay, &overlay_rect);
return;
}
SDL_UnlockSurface(screen);
if (fb.enabled) SDL_Flip(screen);
}