/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+* Artsoft Retro-Game Library *
*----------------------------------------------------------*
-* ©1995 Artsoft Development *
-* Holger Schemel *
-* 33659 Bielefeld-Senne *
-* Telefon: (0521) 493245 *
-* eMail: aeglos@valinor.owl.de *
-* aeglos@uni-paderborn.de *
-* q99492@pbhrzx.uni-paderborn.de *
+* (c) 1994-2002 Artsoft Entertainment *
+* Holger Schemel *
+* Detmolder Strasse 189 *
+* 33604 Bielefeld *
+* Germany *
+* e-mail: info@artsoft.org *
*----------------------------------------------------------*
-* sdl.c *
+* sdl.c *
***********************************************************/
-#include "libgame.h"
+#include "system.h"
+#include "sound.h"
+#include "joystick.h"
+#include "misc.h"
-#ifdef TARGET_SDL
-inline void SDLInitBufferedDisplay(DrawBuffer *backbuffer, DrawWindow *window)
+#if defined(TARGET_SDL)
+
+/* ========================================================================= */
+/* video functions */
+/* ========================================================================= */
+
+/* functions from SGE library */
+inline void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
+
+/* #ifdef PLATFORM_WIN32 */
+#define FULLSCREEN_BUG
+/* #endif */
+
+/* stuff needed to work around SDL/Windows fullscreen drawing bug */
+static int fullscreen_width;
+static int fullscreen_height;
+static int fullscreen_xoffset;
+static int fullscreen_yoffset;
+static int video_xoffset;
+static int video_yoffset;
+
+inline void SDLInitVideoDisplay(void)
{
+ putenv("SDL_VIDEO_CENTERED=1");
+
/* initialize SDL video */
- if (SDL_Init(SDL_INIT_VIDEO) < 0)
- Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
+ Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
+
+ /* set default SDL depth */
+ video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
+}
+
+inline void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
+ boolean fullscreen)
+{
+#ifdef FULLSCREEN_BUG
+ int i;
+ static int screen_xy[][2] =
+ {
+ { 640, 480 },
+ { 800, 600 },
+ { 1024, 768 },
+ { -1, -1 }
+ };
+#endif
+
+ /* default: normal game window size */
+ fullscreen_width = video.width;
+ fullscreen_height = video.height;
+ fullscreen_xoffset = 0;
+ fullscreen_yoffset = 0;
+
+#ifdef FULLSCREEN_BUG
+ for (i=0; screen_xy[i][0] != -1; i++)
+ {
+ if (video.width <= screen_xy[i][0] && video.height <= screen_xy[i][1])
+ {
+ fullscreen_width = screen_xy[i][0];
+ fullscreen_height = screen_xy[i][1];
+ break;
+ }
+ }
- /* automatically cleanup SDL stuff after exit() */
- atexit(SDL_Quit);
+ fullscreen_xoffset = (fullscreen_width - video.width) / 2;
+ fullscreen_yoffset = (fullscreen_height - video.height) / 2;
+#endif
/* open SDL video output device (window or fullscreen mode) */
- if (!SDLSetVideoMode(backbuffer))
+ if (!SDLSetVideoMode(backbuffer, fullscreen))
Error(ERR_EXIT, "setting video mode failed");
/* set window and icon title */
- SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
-
- /* create additional buffer for double-buffering */
- pix[PIX_DB_BACK] = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+ SDL_WM_SetCaption(program.window_title, program.window_title);
/* SDL cannot directly draw to the visible video framebuffer like X11,
but always uses a backbuffer, which is then blitted to the visible
buffer 'window' at the same size as the SDL backbuffer. Although it
should never be drawn to directly, it would do no harm nevertheless. */
- *window = pix[PIX_DB_BACK]; /* 'window' is only symbolic buffer */
- pix[PIX_DB_BACK] = *backbuffer; /* 'backbuffer' is SDL screen buffer */
+ /* create additional (symbolic) buffer for double-buffering */
+ *window = CreateBitmap(video.width, video.height, video.depth);
}
-inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, boolean fullscreen)
+inline boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
{
boolean success = TRUE;
+ int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
+ int surface_flags_window = SURFACE_FLAGS;
+ SDL_Surface *new_surface = NULL;
+
+ if (*backbuffer == NULL)
+ *backbuffer = CreateBitmapStruct();
if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
{
- /* switch display to fullscreen mode, if available */
- DrawWindow window_old = *backbuffer;
- DrawWindow window_new;
+ video_xoffset = fullscreen_xoffset;
+ video_yoffset = fullscreen_yoffset;
- if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
- SDL_HWSURFACE|SDL_FULLSCREEN))
+ /* switch display to fullscreen mode, if available */
+ if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
+ video.depth, surface_flags_fullscreen))
== NULL)
{
/* switching display to fullscreen mode failed */
}
else
{
- if (window_old)
- SDL_FreeSurface(window_old);
- *backbuffer = window_new;
+ (*backbuffer)->surface = new_surface;
video.fullscreen_enabled = TRUE;
success = TRUE;
}
}
- if ((!fullscreen && video.fullscreen_enabled) || !*backbuffer)
+ if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
{
- /* switch display to window mode */
- DrawWindow window_old = *backbuffer;
- DrawWindow window_new;
+ video_xoffset = 0;
+ video_yoffset = 0;
- if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
- SDL_HWSURFACE))
+ /* switch display to window mode */
+ if ((new_surface = SDL_SetVideoMode(video.width, video.height,
+ video.depth, surface_flags_window))
== NULL)
{
/* switching display to window mode failed -- should not happen */
}
else
{
- if (window_old)
- SDL_FreeSurface(window_old);
- *backbuffer = window_new;
+ (*backbuffer)->surface = new_surface;
video.fullscreen_enabled = FALSE;
success = TRUE;
return success;
}
-inline void SDLCopyArea(SDL_Surface *src_surface, SDL_Surface *dst_surface,
+inline void SDLCreateBitmapContent(Bitmap *new_bitmap,
+ int width, int height, int depth)
+{
+ SDL_Surface *surface_tmp, *surface_native;
+
+ if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
+ 0, 0, 0, 0))
+ == NULL)
+ Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+
+ if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
+ Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+
+ SDL_FreeSurface(surface_tmp);
+
+ new_bitmap->surface = surface_native;
+}
+
+inline void SDLFreeBitmapPointers(Bitmap *bitmap)
+{
+ if (bitmap->surface)
+ SDL_FreeSurface(bitmap->surface);
+ if (bitmap->surface_masked)
+ SDL_FreeSurface(bitmap->surface_masked);
+ bitmap->surface = NULL;
+ bitmap->surface_masked = NULL;
+}
+
+inline void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
int src_x, int src_y,
int width, int height,
- int dst_x, int dst_y)
+ int dst_x, int dst_y, int mask_mode)
{
- SDL_Surface *surface = (dst_surface == window ? backbuffer : dst_surface);
+ Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
SDL_Rect src_rect, dst_rect;
+#ifdef FULLSCREEN_BUG
+ if (src_bitmap == backbuffer)
+ {
+ src_x += video_xoffset;
+ src_y += video_yoffset;
+ }
+#endif
+
src_rect.x = src_x;
src_rect.y = src_y;
src_rect.w = width;
src_rect.h = height;
+#ifdef FULLSCREEN_BUG
+ if (dst_bitmap == backbuffer || dst_bitmap == window)
+ {
+ dst_x += video_xoffset;
+ dst_y += video_yoffset;
+ }
+#endif
+
dst_rect.x = dst_x;
dst_rect.y = dst_y;
dst_rect.w = width;
dst_rect.h = height;
- if (src_surface != backbuffer || dst_surface != window)
- SDL_BlitSurface(src_surface, &src_rect, surface, &dst_rect);
+ if (src_bitmap != backbuffer || dst_bitmap != window)
+ SDL_BlitSurface((mask_mode == BLIT_MASKED ?
+ src_bitmap->surface_masked : src_bitmap->surface),
+ &src_rect, real_dst_bitmap->surface, &dst_rect);
- if (dst_surface == window)
- SDL_UpdateRect(backbuffer, dst_x, dst_y, width, height);
+ if (dst_bitmap == window)
+ SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
}
-inline void SDLFillRectangle(SDL_Surface *dst_surface, int x, int y,
- int width, int height, unsigned int color)
+inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
+ int width, int height, Uint32 color)
{
- SDL_Surface *surface = (dst_surface == window ? backbuffer : dst_surface);
+ Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
SDL_Rect rect;
- unsigned int color_r = (color >> 16) && 0xff;
- unsigned int color_g = (color >> 8) && 0xff;
- unsigned int color_b = (color >> 0) && 0xff;
+#if 0
+ unsigned int color_r = (color >> 16) & 0xff;
+ unsigned int color_g = (color >> 8) & 0xff;
+ unsigned int color_b = (color >> 0) & 0xff;
+#endif
+
+#ifdef FULLSCREEN_BUG
+ if (dst_bitmap == backbuffer || dst_bitmap == window)
+ {
+ x += video_xoffset;
+ y += video_yoffset;
+ }
+#endif
rect.x = x;
rect.y = y;
rect.w = width;
rect.h = height;
- SDL_FillRect(surface, &rect,
- SDL_MapRGB(surface->format, color_r, color_g, color_b));
+#if 1
+ SDL_FillRect(real_dst_bitmap->surface, &rect, color);
+#else
+ SDL_FillRect(real_dst_bitmap->surface, &rect,
+ SDL_MapRGB(real_dst_bitmap->surface->format,
+ color_r, color_g, color_b));
+#endif
- if (dst_surface == window)
- SDL_UpdateRect(backbuffer, x, y, width, height);
+ if (dst_bitmap == window)
+ SDL_UpdateRect(backbuffer->surface, x, y, width, height);
}
-inline void SDLDrawSimpleLine(SDL_Surface *surface, int from_x, int from_y,
- int to_x, int to_y, unsigned int color)
+inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
+ int to_x, int to_y, Uint32 color)
{
+ SDL_Surface *surface = dst_bitmap->surface;
SDL_Rect rect;
+#if 0
unsigned int color_r = (color >> 16) & 0xff;
unsigned int color_g = (color >> 8) & 0xff;
unsigned int color_b = (color >> 0) & 0xff;
+#endif
if (from_x > to_x)
swap_numbers(&from_x, &to_x);
rect.w = (to_x - from_x + 1);
rect.h = (to_y - from_y + 1);
+#ifdef FULLSCREEN_BUG
+ if (dst_bitmap == backbuffer || dst_bitmap == window)
+ {
+ rect.x += video_xoffset;
+ rect.y += video_yoffset;
+ }
+#endif
+
+#if 1
+ SDL_FillRect(surface, &rect, color);
+#else
SDL_FillRect(surface, &rect,
SDL_MapRGB(surface->format, color_r, color_g, color_b));
+#endif
}
-inline boolean SDLOpenAudio(void)
+inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
+ int to_x, int to_y, Uint32 color)
{
- if (SDL_Init(SDL_INIT_AUDIO) < 0)
+#ifdef FULLSCREEN_BUG
+ if (dst_bitmap == backbuffer || dst_bitmap == window)
{
- Error(ERR_WARN, "SDL_Init() failed: %s", SDL_GetError());
- return FALSE;
+ from_x += video_xoffset;
+ from_y += video_yoffset;
+ to_x += video_xoffset;
+ to_y += video_yoffset;
+ }
+#endif
+
+ sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
+}
+
+#if 0
+inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
+ int num_points, Uint32 color)
+{
+ int i, x, y;
+ int line_width = 4;
+
+ for (i=0; i<num_points - 1; i++)
+ {
+ for (x=0; x<line_width; x++)
+ {
+ for (y=0; y<line_width; y++)
+ {
+ int dx = x - line_width / 2;
+ int dy = y - line_width / 2;
+
+ if ((x == 0 && y == 0) ||
+ (x == 0 && y == line_width - 1) ||
+ (x == line_width - 1 && y == 0) ||
+ (x == line_width - 1 && y == line_width - 1))
+ continue;
+
+ sge_Line(surface, points[i].x + dx, points[i].y + dy,
+ points[i+1].x + dx, points[i+1].y + dy, color);
+ }
+ }
+ }
+}
+#endif
+
+inline Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
+{
+ SDL_Surface *surface = src_bitmap->surface;
+
+#ifdef FULLSCREEN_BUG
+ if (src_bitmap == backbuffer || src_bitmap == window)
+ {
+ x += video_xoffset;
+ y += video_yoffset;
+ }
+#endif
+
+ switch (surface->format->BytesPerPixel)
+ {
+ case 1: /* assuming 8-bpp */
+ {
+ return *((Uint8 *)surface->pixels + y * surface->pitch + x);
+ }
+ break;
+
+ case 2: /* probably 15-bpp or 16-bpp */
+ {
+ return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
+ }
+ break;
+
+ case 3: /* slow 24-bpp mode; usually not used */
+ {
+ /* does this work? */
+ Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
+ Uint32 color = 0;
+ int shift;
+
+ shift = surface->format->Rshift;
+ color |= *(pix + shift / 8) >> shift;
+ shift = surface->format->Gshift;
+ color |= *(pix + shift / 8) >> shift;
+ shift = surface->format->Bshift;
+ color |= *(pix + shift / 8) >> shift;
+
+ return color;
+ }
+ break;
+
+ case 4: /* probably 32-bpp */
+ {
+ return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+/* ========================================================================= */
+/* The following functions were taken from the SGE library */
+/* (SDL Graphics Extension Library) by Anders Lindström */
+/* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
+/* ========================================================================= */
+
+void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+ if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
+ {
+ switch (surface->format->BytesPerPixel)
+ {
+ case 1:
+ {
+ /* Assuming 8-bpp */
+ *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
+ }
+ break;
+
+ case 2:
+ {
+ /* Probably 15-bpp or 16-bpp */
+ *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
+ }
+ break;
+
+ case 3:
+ {
+ /* Slow 24-bpp mode, usually not used */
+ Uint8 *pix;
+ int shift;
+
+ /* Gack - slow, but endian correct */
+ pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
+ shift = surface->format->Rshift;
+ *(pix+shift/8) = color>>shift;
+ shift = surface->format->Gshift;
+ *(pix+shift/8) = color>>shift;
+ shift = surface->format->Bshift;
+ *(pix+shift/8) = color>>shift;
+ }
+ break;
+
+ case 4:
+ {
+ /* Probably 32-bpp */
+ *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
+ }
+ break;
+ }
}
+}
+
+void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
+ Uint8 R, Uint8 G, Uint8 B)
+{
+ _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
+}
+
+void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+ *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
+}
+
+void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+ *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
+}
+
+void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+ Uint8 *pix;
+ int shift;
- if (Mix_OpenAudio(22050, AUDIO_S16, 2, 512) < 0)
+ /* Gack - slow, but endian correct */
+ pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
+ shift = surface->format->Rshift;
+ *(pix+shift/8) = color>>shift;
+ shift = surface->format->Gshift;
+ *(pix+shift/8) = color>>shift;
+ shift = surface->format->Bshift;
+ *(pix+shift/8) = color>>shift;
+}
+
+void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+ *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
+}
+
+void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
+{
+ switch (dest->format->BytesPerPixel)
+ {
+ case 1:
+ *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
+ break;
+
+ case 2:
+ *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
+ break;
+
+ case 3:
+ _PutPixel24(dest,x,y,color);
+ break;
+
+ case 4:
+ *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
+ break;
+ }
+}
+
+void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
+{
+ if (SDL_MUSTLOCK(surface))
+ {
+ if (SDL_LockSurface(surface) < 0)
+ {
+ return;
+ }
+ }
+
+ _PutPixel(surface, x, y, color);
+
+ if (SDL_MUSTLOCK(surface))
+ {
+ SDL_UnlockSurface(surface);
+ }
+}
+
+void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
+ Uint8 r, Uint8 g, Uint8 b)
+{
+ sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
+}
+
+Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
+{
+ if (y >= 0 && y <= dest->h - 1)
+ {
+ switch (dest->format->BytesPerPixel)
+ {
+ case 1:
+ return y*dest->pitch;
+ break;
+
+ case 2:
+ return y*dest->pitch/2;
+ break;
+
+ case 3:
+ return y*dest->pitch;
+ break;
+
+ case 4:
+ return y*dest->pitch/4;
+ break;
+ }
+ }
+
+ return -1;
+}
+
+void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
+{
+ if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
+ {
+ switch (surface->format->BytesPerPixel)
+ {
+ case 1:
+ {
+ /* Assuming 8-bpp */
+ *((Uint8 *)surface->pixels + ypitch + x) = color;
+ }
+ break;
+
+ case 2:
+ {
+ /* Probably 15-bpp or 16-bpp */
+ *((Uint16 *)surface->pixels + ypitch + x) = color;
+ }
+ break;
+
+ case 3:
+ {
+ /* Slow 24-bpp mode, usually not used */
+ Uint8 *pix;
+ int shift;
+
+ /* Gack - slow, but endian correct */
+ pix = (Uint8 *)surface->pixels + ypitch + x*3;
+ shift = surface->format->Rshift;
+ *(pix+shift/8) = color>>shift;
+ shift = surface->format->Gshift;
+ *(pix+shift/8) = color>>shift;
+ shift = surface->format->Bshift;
+ *(pix+shift/8) = color>>shift;
+ }
+ break;
+
+ case 4:
+ {
+ /* Probably 32-bpp */
+ *((Uint32 *)surface->pixels + ypitch + x) = color;
+ }
+ break;
+ }
+ }
+}
+
+void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
+ Uint32 Color)
+{
+ SDL_Rect l;
+
+ if (SDL_MUSTLOCK(Surface))
+ {
+ if (SDL_LockSurface(Surface) < 0)
+ {
+ return;
+ }
+ }
+
+ if (x1 > x2)
+ {
+ Sint16 tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+
+ /* Do the clipping */
+ if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
+ return;
+ if (x1 < 0)
+ x1 = 0;
+ if (x2 > Surface->w - 1)
+ x2 = Surface->w - 1;
+
+ l.x = x1;
+ l.y = y;
+ l.w = x2 - x1 + 1;
+ l.h = 1;
+
+ SDL_FillRect(Surface, &l, Color);
+
+ if (SDL_MUSTLOCK(Surface))
+ {
+ SDL_UnlockSurface(Surface);
+ }
+}
+
+void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
+ Uint8 R, Uint8 G, Uint8 B)
+{
+ sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
+}
+
+void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
+{
+ SDL_Rect l;
+
+ if (x1 > x2)
+ {
+ Sint16 tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+
+ /* Do the clipping */
+ if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
+ return;
+ if (x1 < 0)
+ x1 = 0;
+ if (x2 > Surface->w - 1)
+ x2 = Surface->w - 1;
+
+ l.x = x1;
+ l.y = y;
+ l.w = x2 - x1 + 1;
+ l.h = 1;
+
+ SDL_FillRect(Surface, &l, Color);
+}
+
+void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
+ Uint32 Color)
+{
+ SDL_Rect l;
+
+ if (SDL_MUSTLOCK(Surface))
+ {
+ if (SDL_LockSurface(Surface) < 0)
+ {
+ return;
+ }
+ }
+
+ if (y1 > y2)
+ {
+ Sint16 tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ }
+
+ /* Do the clipping */
+ if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
+ return;
+ if (y1 < 0)
+ y1 = 0;
+ if (y2 > Surface->h - 1)
+ y2 = Surface->h - 1;
+
+ l.x = x;
+ l.y = y1;
+ l.w = 1;
+ l.h = y2 - y1 + 1;
+
+ SDL_FillRect(Surface, &l, Color);
+
+ if (SDL_MUSTLOCK(Surface))
+ {
+ SDL_UnlockSurface(Surface);
+ }
+}
+
+void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
+ Uint8 R, Uint8 G, Uint8 B)
+{
+ sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
+}
+
+void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
+{
+ SDL_Rect l;
+
+ if (y1 > y2)
+ {
+ Sint16 tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ }
+
+ /* Do the clipping */
+ if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
+ return;
+ if (y1 < 0)
+ y1 = 0;
+ if (y2 > Surface->h - 1)
+ y2 = Surface->h - 1;
+
+ l.x = x;
+ l.y = y1;
+ l.w = 1;
+ l.h = y2 - y1 + 1;
+
+ SDL_FillRect(Surface, &l, Color);
+}
+
+void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
+ Sint16 x2, Sint16 y2, Uint32 Color,
+ void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
+ Uint32 Color))
+{
+ Sint16 dx, dy, sdx, sdy, x, y, px, py;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+
+ sdx = (dx < 0) ? -1 : 1;
+ sdy = (dy < 0) ? -1 : 1;
+
+ dx = sdx * dx + 1;
+ dy = sdy * dy + 1;
+
+ x = y = 0;
+
+ px = x1;
+ py = y1;
+
+ if (dx >= dy)
+ {
+ for (x = 0; x < dx; x++)
+ {
+ Callback(Surface, px, py, Color);
+
+ y += dy;
+ if (y >= dx)
+ {
+ y -= dx;
+ py += sdy;
+ }
+
+ px += sdx;
+ }
+ }
+ else
+ {
+ for (y = 0; y < dy; y++)
+ {
+ Callback(Surface, px, py, Color);
+
+ x += dx;
+ if (x >= dy)
+ {
+ x -= dy;
+ px += sdx;
+ }
+
+ py += sdy;
+ }
+ }
+}
+
+void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
+ Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
+ void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
+ Uint32 Color))
+{
+ sge_DoLine(Surface, X1, Y1, X2, Y2,
+ SDL_MapRGB(Surface->format, R, G, B), Callback);
+}
+
+void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
+ Uint32 Color)
+{
+ if (SDL_MUSTLOCK(Surface))
+ {
+ if (SDL_LockSurface(Surface) < 0)
+ return;
+ }
+
+ /* Draw the line */
+ sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
+
+ /* unlock the display */
+ if (SDL_MUSTLOCK(Surface))
+ {
+ SDL_UnlockSurface(Surface);
+ }
+}
+
+void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
+ Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
+{
+ sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
+}
+
+inline void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
+{
+#ifdef FULLSCREEN_BUG
+ if (dst_bitmap == backbuffer || dst_bitmap == window)
+ {
+ x += video_xoffset;
+ y += video_yoffset;
+ }
+#endif
+
+ sge_PutPixel(dst_bitmap->surface, x, y, pixel);
+}
+
+
+/*
+ -----------------------------------------------------------------------------
+ quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
+ -----------------------------------------------------------------------------
+*/
+
+inline void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
+ int width, int height, Uint32 color)
+{
+ int x, y;
+
+ for (y=src_y; y < src_y + height; y++)
+ {
+ for (x=src_x; x < src_x + width; x++)
+ {
+ Uint32 pixel = SDLGetPixel(bitmap, x, y);
+
+ SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
+ }
+ }
+}
+
+inline void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+ int src_x, int src_y, int width, int height,
+ int dst_x, int dst_y)
+{
+ int x, y;
+
+ for (y=0; y < height; y++)
+ {
+ for (x=0; x < width; x++)
+ {
+ Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
+
+ if (pixel != BLACK_PIXEL)
+ SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
+ }
+ }
+}
+
+
+/* ========================================================================= */
+/* The following functions were taken from the SDL_gfx library version 2.0.3 */
+/* (Rotozoomer) by Andreas Schiffler */
+/* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
+/* ========================================================================= */
+
+/*
+ -----------------------------------------------------------------------------
+ 32 bit zoomer
+
+ zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
+ -----------------------------------------------------------------------------
+*/
+
+typedef struct
+{
+ Uint8 r;
+ Uint8 g;
+ Uint8 b;
+ Uint8 a;
+} tColorRGBA;
+
+int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
+{
+ int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
+ tColorRGBA *sp, *csp, *dp;
+ int sgap, dgap;
+
+ /* variable setup */
+ sx = (int) (65536.0 * (float) src->w / (float) dst->w);
+ sy = (int) (65536.0 * (float) src->h / (float) dst->h);
+
+ /* allocate memory for row increments */
+ sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
+ say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
+
+ /* precalculate row increments */
+ csx = 0;
+ csax = sax;
+ for (x = 0; x <= dst->w; x++)
+ {
+ *csax = csx;
+ csax++;
+ csx &= 0xffff;
+ csx += sx;
+ }
+
+ csy = 0;
+ csay = say;
+ for (y = 0; y <= dst->h; y++)
+ {
+ *csay = csy;
+ csay++;
+ csy &= 0xffff;
+ csy += sy;
+ }
+
+ /* pointer setup */
+ sp = csp = (tColorRGBA *) src->pixels;
+ dp = (tColorRGBA *) dst->pixels;
+ sgap = src->pitch - src->w * 4;
+ dgap = dst->pitch - dst->w * 4;
+
+ csay = say;
+ for (y = 0; y < dst->h; y++)
+ {
+ sp = csp;
+ csax = sax;
+
+ for (x = 0; x < dst->w; x++)
+ {
+ /* draw */
+ *dp = *sp;
+
+ /* advance source pointers */
+ csax++;
+ sp += (*csax >> 16);
+
+ /* advance destination pointer */
+ dp++;
+ }
+
+ /* advance source pointer */
+ csay++;
+ csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
+
+ /* advance destination pointers */
+ dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
+ }
+
+ free(sax);
+ free(say);
+
+ return 0;
+}
+
+/*
+ -----------------------------------------------------------------------------
+ 8 bit zoomer
+
+ zoomes 8 bit palette/Y 'src' surface to 'dst' surface
+ -----------------------------------------------------------------------------
+*/
+
+int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
+{
+ Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
+ Uint8 *sp, *dp, *csp;
+ int dgap;
+
+ /* variable setup */
+ sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
+ sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
+
+ /* allocate memory for row increments */
+ sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
+ say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
+
+ /* precalculate row increments */
+ csx = 0;
+ csax = sax;
+ for (x = 0; x < dst->w; x++)
+ {
+ csx += sx;
+ *csax = (csx >> 16);
+ csx &= 0xffff;
+ csax++;
+ }
+
+ csy = 0;
+ csay = say;
+ for (y = 0; y < dst->h; y++)
+ {
+ csy += sy;
+ *csay = (csy >> 16);
+ csy &= 0xffff;
+ csay++;
+ }
+
+ csx = 0;
+ csax = sax;
+ for (x = 0; x < dst->w; x++)
+ {
+ csx += (*csax);
+ csax++;
+ }
+
+ csy = 0;
+ csay = say;
+ for (y = 0; y < dst->h; y++)
+ {
+ csy += (*csay);
+ csay++;
+ }
+
+ /* pointer setup */
+ sp = csp = (Uint8 *) src->pixels;
+ dp = (Uint8 *) dst->pixels;
+ dgap = dst->pitch - dst->w;
+
+ /* draw */
+ csay = say;
+ for (y = 0; y < dst->h; y++)
+ {
+ csax = sax;
+ sp = csp;
+ for (x = 0; x < dst->w; x++)
+ {
+ /* draw */
+ *dp = *sp;
+
+ /* advance source pointers */
+ sp += (*csax);
+ csax++;
+
+ /* advance destination pointer */
+ dp++;
+ }
+
+ /* advance source pointer (for row) */
+ csp += ((*csay) * src->pitch);
+ csay++;
+
+ /* advance destination pointers */
+ dp += dgap;
+ }
+
+ free(sax);
+ free(say);
+
+ return 0;
+}
+
+/*
+ -----------------------------------------------------------------------------
+ zoomSurface()
+
+ Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
+ 'zoomx' and 'zoomy' are scaling factors for width and height.
+ If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
+ If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
+ into a 32bit RGBA format on the fly.
+ -----------------------------------------------------------------------------
+*/
+
+SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
+{
+ SDL_Surface *zoom_src = NULL;
+ SDL_Surface *zoom_dst = NULL;
+ boolean is_converted = FALSE;
+ boolean is_32bit;
+ int i;
+
+ if (src == NULL)
+ return NULL;
+
+ /* determine if source surface is 32 bit or 8 bit */
+ is_32bit = (src->format->BitsPerPixel == 32);
+
+ if (is_32bit || src->format->BitsPerPixel == 8)
+ {
+ /* use source surface 'as is' */
+ zoom_src = src;
+ }
+ else
+ {
+ /* new source surface is 32 bit with a defined RGB ordering */
+ zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
+ 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
+ SDL_BlitSurface(src, NULL, zoom_src, NULL);
+ is_32bit = TRUE;
+ is_converted = TRUE;
+ }
+
+ /* allocate surface to completely contain the zoomed surface */
+ if (is_32bit)
+ {
+ /* target surface is 32 bit with source RGBA/ABGR ordering */
+ zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
+ zoom_src->format->Rmask,
+ zoom_src->format->Gmask,
+ zoom_src->format->Bmask, 0);
+ }
+ else
+ {
+ /* target surface is 8 bit */
+ zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
+ 0, 0, 0, 0);
+ }
+
+ /* lock source surface */
+ SDL_LockSurface(zoom_src);
+
+ /* check which kind of surface we have */
+ if (is_32bit)
+ {
+ /* call the 32 bit transformation routine to do the zooming */
+ zoomSurfaceRGBA(zoom_src, zoom_dst);
+ }
+ else
+ {
+ /* copy palette */
+ for (i=0; i < zoom_src->format->palette->ncolors; i++)
+ zoom_dst->format->palette->colors[i] =
+ zoom_src->format->palette->colors[i];
+ zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
+
+ /* call the 8 bit transformation routine to do the zooming */
+ zoomSurfaceY(zoom_src, zoom_dst);
+ }
+
+ /* unlock source surface */
+ SDL_UnlockSurface(zoom_src);
+
+ /* free temporary surface */
+ if (is_converted)
+ SDL_FreeSurface(zoom_src);
+
+ /* return destination surface */
+ return zoom_dst;
+}
+
+void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
+{
+ SDL_Surface *sdl_surface_tmp;
+ int dst_width = dst_bitmap->width;
+ int dst_height = dst_bitmap->height;
+
+ /* throw away old destination surface */
+ SDL_FreeSurface(dst_bitmap->surface);
+
+ /* create zoomed temporary surface from source surface */
+ sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
+
+ /* create native format destination surface from zoomed temporary surface */
+ dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
+
+ /* free temporary surface */
+ SDL_FreeSurface(sdl_surface_tmp);
+}
+
+
+/* ========================================================================= */
+/* load image to bitmap */
+/* ========================================================================= */
+
+Bitmap *SDLLoadImage(char *filename)
+{
+ Bitmap *new_bitmap = CreateBitmapStruct();
+ SDL_Surface *sdl_image_tmp;
+
+ /* load image to temporary surface */
+ if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
+ {
+ SetError("IMG_Load(): %s", SDL_GetError());
+ return NULL;
+ }
+
+ /* create native non-transparent surface for current image */
+ if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
+ {
+ SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+ return NULL;
+ }
+
+ /* create native transparent surface for current image */
+ SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
+ SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
+ if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
+ {
+ SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+ return NULL;
+ }
+
+ /* free temporary surface */
+ SDL_FreeSurface(sdl_image_tmp);
+
+ new_bitmap->width = new_bitmap->surface->w;
+ new_bitmap->height = new_bitmap->surface->h;
+
+ return new_bitmap;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* custom cursor fuctions */
+/* ------------------------------------------------------------------------- */
+
+static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
+{
+ return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
+ cursor_info->width, cursor_info->height,
+ cursor_info->hot_x, cursor_info->hot_y);
+}
+
+void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
+{
+ static struct MouseCursorInfo *last_cursor_info = NULL;
+ static SDL_Cursor *cursor_default = NULL;
+ static SDL_Cursor *cursor_current = NULL;
+
+ if (cursor_default == NULL)
+ cursor_default = SDL_GetCursor();
+
+ if (cursor_info != NULL && cursor_info != last_cursor_info)
+ {
+ cursor_current = create_cursor(cursor_info);
+ last_cursor_info = cursor_info;
+ }
+
+ SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
+}
+
+
+/* ========================================================================= */
+/* audio functions */
+/* ========================================================================= */
+
+inline void SDLOpenAudio(void)
+{
+ if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
+ putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
+
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
+ {
+ Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
+ return;
+ }
+
+ if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
+ AUDIO_NUM_CHANNELS_STEREO,
+ setup.system.audio_fragment_size) < 0)
{
Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
- return FALSE;
+ return;
}
- Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
- Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
+ audio.sound_available = TRUE;
+ audio.music_available = TRUE;
+ audio.loops_available = TRUE;
+ audio.sound_enabled = TRUE;
- return TRUE;
+ /* set number of available mixer channels */
+ audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
+ audio.music_channel = MUSIC_CHANNEL;
+ audio.first_sound_channel = FIRST_SOUND_CHANNEL;
+
+ Mixer_InitChannels();
}
inline void SDLCloseAudio(void)
Mix_HaltChannel(-1);
Mix_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+}
+
+
+/* ========================================================================= */
+/* event functions */
+/* ========================================================================= */
+
+inline void SDLNextEvent(Event *event)
+{
+ SDL_WaitEvent(event);
+
+#ifdef FULLSCREEN_BUG
+ if (event->type == EVENT_BUTTONPRESS ||
+ event->type == EVENT_BUTTONRELEASE)
+ {
+ if (((ButtonEvent *)event)->x > video_xoffset)
+ ((ButtonEvent *)event)->x -= video_xoffset;
+ else
+ ((ButtonEvent *)event)->x = 0;
+ if (((ButtonEvent *)event)->y > video_yoffset)
+ ((ButtonEvent *)event)->y -= video_yoffset;
+ else
+ ((ButtonEvent *)event)->y = 0;
+ }
+ else if (event->type == EVENT_MOTIONNOTIFY)
+ {
+ if (((MotionEvent *)event)->x > video_xoffset)
+ ((MotionEvent *)event)->x -= video_xoffset;
+ else
+ ((MotionEvent *)event)->x = 0;
+ if (((MotionEvent *)event)->y > video_yoffset)
+ ((MotionEvent *)event)->y -= video_yoffset;
+ else
+ ((MotionEvent *)event)->y = 0;
+ }
+#endif
+}
+
+
+/* ========================================================================= */
+/* joystick functions */
+/* ========================================================================= */
+
+static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
+static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+
+static boolean SDLOpenJoystick(int nr)
+{
+ if (nr < 0 || nr > MAX_PLAYERS)
+ return FALSE;
+
+ return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
+}
+
+static void SDLCloseJoystick(int nr)
+{
+ if (nr < 0 || nr > MAX_PLAYERS)
+ return;
+
+ SDL_JoystickClose(sdl_joystick[nr]);
+}
+
+static boolean SDLCheckJoystickOpened(int nr)
+{
+ if (nr < 0 || nr > MAX_PLAYERS)
+ return FALSE;
+
+ return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
+}
+
+void HandleJoystickEvent(Event *event)
+{
+ switch(event->type)
+ {
+ case SDL_JOYAXISMOTION:
+ if (event->jaxis.axis < 2)
+ sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
+ break;
+
+ case SDL_JOYBUTTONDOWN:
+ if (event->jbutton.button < 2)
+ sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
+ break;
+
+ case SDL_JOYBUTTONUP:
+ if (event->jbutton.button < 2)
+ sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void SDLInitJoysticks()
+{
+ static boolean sdl_joystick_subsystem_initialized = FALSE;
+ int i;
+
+ if (!sdl_joystick_subsystem_initialized)
+ {
+ sdl_joystick_subsystem_initialized = TRUE;
+
+ if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
+ {
+ Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
+ return;
+ }
+ }
+
+ for (i=0; i<MAX_PLAYERS; i++)
+ {
+ char *device_name = setup.input[i].joy.device_name;
+ int joystick_nr = getJoystickNrFromDeviceName(device_name);
+
+ if (joystick_nr >= SDL_NumJoysticks())
+ joystick_nr = -1;
+
+ /* misuse joystick file descriptor variable to store joystick number */
+ joystick.fd[i] = joystick_nr;
+
+ /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
+ if (SDLCheckJoystickOpened(joystick_nr))
+ SDLCloseJoystick(joystick_nr);
+
+ if (!setup.input[i].use_joystick)
+ continue;
+
+ if (!SDLOpenJoystick(joystick_nr))
+ {
+ Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
+ continue;
+ }
+
+ joystick.status = JOYSTICK_ACTIVATED;
+ }
+}
+
+boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
+{
+ if (nr < 0 || nr >= MAX_PLAYERS)
+ return FALSE;
+
+ if (x != NULL)
+ *x = sdl_js_axis[nr][0];
+ if (y != NULL)
+ *y = sdl_js_axis[nr][1];
+
+ if (b1 != NULL)
+ *b1 = sdl_js_button[nr][0];
+ if (b2 != NULL)
+ *b2 = sdl_js_button[nr][1];
+
+ return TRUE;
}
#endif /* TARGET_SDL */