1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
20 #if defined(TARGET_SDL)
22 /* ========================================================================= */
24 /* ========================================================================= */
26 /* functions from SGE library */
27 inline void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
30 #define FULLSCREEN_BUG
33 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
34 static int fullscreen_width;
35 static int fullscreen_height;
36 static int fullscreen_xoffset;
37 static int fullscreen_yoffset;
38 static int video_xoffset;
39 static int video_yoffset;
41 inline void SDLInitVideoDisplay(void)
43 /* initialize SDL video */
44 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
45 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
47 /* set default SDL depth */
48 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
51 inline void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
56 static int screen_xy[][2] =
65 /* default: normal game window size */
66 fullscreen_width = video.width;
67 fullscreen_height = video.height;
68 fullscreen_xoffset = 0;
69 fullscreen_yoffset = 0;
72 for (i=0; screen_xy[i][0] != -1; i++)
74 if (video.width <= screen_xy[i][0] && video.height <= screen_xy[i][1])
76 fullscreen_width = screen_xy[i][0];
77 fullscreen_height = screen_xy[i][1];
82 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
83 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
86 /* open SDL video output device (window or fullscreen mode) */
87 if (!SDLSetVideoMode(backbuffer, fullscreen))
88 Error(ERR_EXIT, "setting video mode failed");
90 /* set window and icon title */
91 SDL_WM_SetCaption(program.window_title, program.window_title);
93 /* SDL cannot directly draw to the visible video framebuffer like X11,
94 but always uses a backbuffer, which is then blitted to the visible
95 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
96 visible video framebuffer with 'SDL_Flip', if the hardware supports
97 this). Therefore do not use an additional backbuffer for drawing, but
98 use a symbolic buffer (distinguishable from the SDL backbuffer) called
99 'window', which indicates that the SDL backbuffer should be updated to
100 the visible video framebuffer when attempting to blit to it.
102 For convenience, it seems to be a good idea to create this symbolic
103 buffer 'window' at the same size as the SDL backbuffer. Although it
104 should never be drawn to directly, it would do no harm nevertheless. */
106 /* create additional (symbolic) buffer for double-buffering */
107 *window = CreateBitmap(video.width, video.height, video.depth);
110 inline boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
112 boolean success = TRUE;
113 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
114 int surface_flags_window = SURFACE_FLAGS;
115 SDL_Surface *new_surface = NULL;
117 if (*backbuffer == NULL)
118 *backbuffer = CreateBitmapStruct();
120 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
122 video_xoffset = fullscreen_xoffset;
123 video_yoffset = fullscreen_yoffset;
125 /* switch display to fullscreen mode, if available */
126 if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
127 video.depth, surface_flags_fullscreen))
130 /* switching display to fullscreen mode failed */
131 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
133 /* do not try it again */
134 video.fullscreen_available = FALSE;
139 (*backbuffer)->surface = new_surface;
141 video.fullscreen_enabled = TRUE;
146 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
151 /* switch display to window mode */
152 if ((new_surface = SDL_SetVideoMode(video.width, video.height,
153 video.depth, surface_flags_window))
156 /* switching display to window mode failed -- should not happen */
157 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
163 (*backbuffer)->surface = new_surface;
165 video.fullscreen_enabled = FALSE;
173 inline void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
174 int src_x, int src_y,
175 int width, int height,
176 int dst_x, int dst_y, int copy_mode)
178 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
179 SDL_Rect src_rect, dst_rect;
181 #ifdef FULLSCREEN_BUG
182 if (src_bitmap == backbuffer)
184 src_x += video_xoffset;
185 src_y += video_yoffset;
194 #ifdef FULLSCREEN_BUG
195 if (dst_bitmap == backbuffer || dst_bitmap == window)
197 dst_x += video_xoffset;
198 dst_y += video_yoffset;
207 if (src_bitmap != backbuffer || dst_bitmap != window)
208 SDL_BlitSurface((copy_mode == SDLCOPYAREA_MASKED ?
209 src_bitmap->surface_masked : src_bitmap->surface),
210 &src_rect, real_dst_bitmap->surface, &dst_rect);
212 if (dst_bitmap == window)
213 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
216 inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
217 int width, int height, unsigned int color)
219 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
221 unsigned int color_r = (color >> 16) && 0xff;
222 unsigned int color_g = (color >> 8) && 0xff;
223 unsigned int color_b = (color >> 0) && 0xff;
225 #ifdef FULLSCREEN_BUG
226 if (dst_bitmap == backbuffer || dst_bitmap == window)
238 SDL_FillRect(real_dst_bitmap->surface, &rect,
239 SDL_MapRGB(real_dst_bitmap->surface->format,
240 color_r, color_g, color_b));
242 if (dst_bitmap == window)
243 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
246 inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
247 int to_x, int to_y, unsigned int color)
249 SDL_Surface *surface = dst_bitmap->surface;
251 unsigned int color_r = (color >> 16) & 0xff;
252 unsigned int color_g = (color >> 8) & 0xff;
253 unsigned int color_b = (color >> 0) & 0xff;
256 swap_numbers(&from_x, &to_x);
259 swap_numbers(&from_y, &to_y);
263 rect.w = (to_x - from_x + 1);
264 rect.h = (to_y - from_y + 1);
266 #ifdef FULLSCREEN_BUG
267 if (dst_bitmap == backbuffer || dst_bitmap == window)
269 rect.x += video_xoffset;
270 rect.y += video_yoffset;
274 SDL_FillRect(surface, &rect,
275 SDL_MapRGB(surface->format, color_r, color_g, color_b));
278 inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
279 int to_x, int to_y, Uint32 color)
281 #ifdef FULLSCREEN_BUG
282 if (dst_bitmap == backbuffer || dst_bitmap == window)
284 from_x += video_xoffset;
285 from_y += video_yoffset;
286 to_x += video_xoffset;
287 to_y += video_yoffset;
291 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
295 inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
296 int num_points, Uint32 color)
301 for (i=0; i<num_points - 1; i++)
303 for (x=0; x<line_width; x++)
305 for (y=0; y<line_width; y++)
307 int dx = x - line_width / 2;
308 int dy = y - line_width / 2;
310 if ((x == 0 && y == 0) ||
311 (x == 0 && y == line_width - 1) ||
312 (x == line_width - 1 && y == 0) ||
313 (x == line_width - 1 && y == line_width - 1))
316 sge_Line(surface, points[i].x + dx, points[i].y + dy,
317 points[i+1].x + dx, points[i+1].y + dy, color);
324 inline Pixel SDLGetPixel(Bitmap *dst_bitmap, int x, int y)
326 SDL_Surface *surface = dst_bitmap->surface;
328 #ifdef FULLSCREEN_BUG
329 if (dst_bitmap == backbuffer || dst_bitmap == window)
336 switch (surface->format->BytesPerPixel)
338 case 1: /* assuming 8-bpp */
340 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
344 case 2: /* probably 15-bpp or 16-bpp */
346 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
350 case 3: /* slow 24-bpp mode; usually not used */
352 /* does this work? */
353 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
357 shift = surface->format->Rshift;
358 color |= *(pix + shift / 8) >> shift;
359 shift = surface->format->Gshift;
360 color |= *(pix + shift / 8) >> shift;
361 shift = surface->format->Bshift;
362 color |= *(pix + shift / 8) >> shift;
368 case 4: /* probably 32-bpp */
370 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
379 /* ========================================================================= */
380 /* The following functions have been taken from the SGE library */
381 /* (SDL Graphics Extension Library) by Anders Lindström */
382 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
383 /* ========================================================================= */
385 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
387 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
389 switch (surface->format->BytesPerPixel)
394 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
400 /* Probably 15-bpp or 16-bpp */
401 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
407 /* Slow 24-bpp mode, usually not used */
411 /* Gack - slow, but endian correct */
412 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
413 shift = surface->format->Rshift;
414 *(pix+shift/8) = color>>shift;
415 shift = surface->format->Gshift;
416 *(pix+shift/8) = color>>shift;
417 shift = surface->format->Bshift;
418 *(pix+shift/8) = color>>shift;
424 /* Probably 32-bpp */
425 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
432 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
433 Uint8 R, Uint8 G, Uint8 B)
435 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
438 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
440 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
443 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
445 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
448 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
453 /* Gack - slow, but endian correct */
454 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
455 shift = surface->format->Rshift;
456 *(pix+shift/8) = color>>shift;
457 shift = surface->format->Gshift;
458 *(pix+shift/8) = color>>shift;
459 shift = surface->format->Bshift;
460 *(pix+shift/8) = color>>shift;
463 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
465 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
468 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
470 switch (dest->format->BytesPerPixel)
473 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
477 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
481 _PutPixel24(dest,x,y,color);
485 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
490 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
492 if (SDL_MUSTLOCK(surface))
494 if (SDL_LockSurface(surface) < 0)
500 _PutPixel(surface, x, y, color);
502 if (SDL_MUSTLOCK(surface))
504 SDL_UnlockSurface(surface);
508 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
509 Uint8 R, Uint8 G, Uint8 B)
511 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
514 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
516 if (y >= 0 && y <= dest->h - 1)
518 switch (dest->format->BytesPerPixel)
521 return y*dest->pitch;
525 return y*dest->pitch/2;
529 return y*dest->pitch;
533 return y*dest->pitch/4;
541 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
543 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
545 switch (surface->format->BytesPerPixel)
550 *((Uint8 *)surface->pixels + ypitch + x) = color;
556 /* Probably 15-bpp or 16-bpp */
557 *((Uint16 *)surface->pixels + ypitch + x) = color;
563 /* Slow 24-bpp mode, usually not used */
567 /* Gack - slow, but endian correct */
568 pix = (Uint8 *)surface->pixels + ypitch + x*3;
569 shift = surface->format->Rshift;
570 *(pix+shift/8) = color>>shift;
571 shift = surface->format->Gshift;
572 *(pix+shift/8) = color>>shift;
573 shift = surface->format->Bshift;
574 *(pix+shift/8) = color>>shift;
580 /* Probably 32-bpp */
581 *((Uint32 *)surface->pixels + ypitch + x) = color;
588 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
593 if (SDL_MUSTLOCK(Surface))
595 if (SDL_LockSurface(Surface) < 0)
608 /* Do the clipping */
609 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
613 if (x2 > Surface->w - 1)
621 SDL_FillRect(Surface, &l, Color);
623 if (SDL_MUSTLOCK(Surface))
625 SDL_UnlockSurface(Surface);
629 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
630 Uint8 R, Uint8 G, Uint8 B)
632 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
635 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
646 /* Do the clipping */
647 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
651 if (x2 > Surface->w - 1)
659 SDL_FillRect(Surface, &l, Color);
662 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
667 if (SDL_MUSTLOCK(Surface))
669 if (SDL_LockSurface(Surface) < 0)
682 /* Do the clipping */
683 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
687 if (y2 > Surface->h - 1)
695 SDL_FillRect(Surface, &l, Color);
697 if (SDL_MUSTLOCK(Surface))
699 SDL_UnlockSurface(Surface);
703 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
704 Uint8 R, Uint8 G, Uint8 B)
706 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
709 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
720 /* Do the clipping */
721 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
725 if (y2 > Surface->h - 1)
733 SDL_FillRect(Surface, &l, Color);
736 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
737 Sint16 x2, Sint16 y2, Uint32 Color,
738 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
741 Sint16 dx, dy, sdx, sdy, x, y, px, py;
746 sdx = (dx < 0) ? -1 : 1;
747 sdy = (dy < 0) ? -1 : 1;
759 for (x = 0; x < dx; x++)
761 Callback(Surface, px, py, Color);
775 for (y = 0; y < dy; y++)
777 Callback(Surface, px, py, Color);
791 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
792 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
793 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
796 sge_DoLine(Surface, X1, Y1, X2, Y2,
797 SDL_MapRGB(Surface->format, R, G, B), Callback);
800 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
803 if (SDL_MUSTLOCK(Surface))
805 if (SDL_LockSurface(Surface) < 0)
810 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
812 /* unlock the display */
813 if (SDL_MUSTLOCK(Surface))
815 SDL_UnlockSurface(Surface);
819 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
820 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
822 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
825 Bitmap *SDLLoadImage(char *filename)
827 Bitmap *new_bitmap = CreateBitmapStruct();
828 SDL_Surface *sdl_image_tmp;
830 /* load image to temporary surface */
831 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
833 SetError("IMG_Load(): %s", SDL_GetError());
837 /* create native non-transparent surface for current image */
838 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
840 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
844 /* create native transparent surface for current image */
845 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
846 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
847 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
849 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
853 /* free temporary surface */
854 SDL_FreeSurface(sdl_image_tmp);
856 new_bitmap->width = new_bitmap->surface->w;
857 new_bitmap->height = new_bitmap->surface->h;
863 /* ========================================================================= */
864 /* audio functions */
865 /* ========================================================================= */
867 inline void SDLOpenAudio(void)
869 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
871 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
875 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, AUDIO_S16,
876 AUDIO_STEREO_CHANNELS,
877 DEFAULT_AUDIO_FRAGMENT_SIZE) < 0)
879 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
883 audio.sound_available = TRUE;
884 audio.music_available = TRUE;
885 audio.loops_available = TRUE;
886 audio.sound_enabled = TRUE;
888 /* determine number of available channels */
889 audio.channels = Mix_AllocateChannels(MIX_CHANNELS);
891 /* reserve first channel for music loops */
892 if (Mix_ReserveChannels(1) == 1)
893 audio.music_channel = 0;
895 audio.music_available = FALSE;
897 Mix_Volume(-1, SOUND_MAX_VOLUME);
898 Mix_VolumeMusic(SOUND_MAX_VOLUME);
901 inline void SDLCloseAudio(void)
907 SDL_QuitSubSystem(SDL_INIT_AUDIO);
911 /* ========================================================================= */
912 /* event functions */
913 /* ========================================================================= */
915 inline void SDLNextEvent(Event *event)
917 SDL_WaitEvent(event);
919 #ifdef FULLSCREEN_BUG
920 if (event->type == EVENT_BUTTONPRESS ||
921 event->type == EVENT_BUTTONRELEASE)
923 if (((ButtonEvent *)event)->x > video_xoffset)
924 ((ButtonEvent *)event)->x -= video_xoffset;
926 ((ButtonEvent *)event)->x = 0;
927 if (((ButtonEvent *)event)->y > video_yoffset)
928 ((ButtonEvent *)event)->y -= video_yoffset;
930 ((ButtonEvent *)event)->y = 0;
932 else if (event->type == EVENT_MOTIONNOTIFY)
934 if (((ButtonEvent *)event)->x > video_xoffset)
935 ((ButtonEvent *)event)->x -= video_xoffset;
937 ((ButtonEvent *)event)->x = 0;
938 if (((ButtonEvent *)event)->y > video_yoffset)
939 ((ButtonEvent *)event)->y -= video_yoffset;
941 ((ButtonEvent *)event)->y = 0;
947 /* ========================================================================= */
948 /* joystick functions */
949 /* ========================================================================= */
951 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
952 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
953 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
955 static boolean SDLOpenJoystick(int nr)
957 if (nr < 0 || nr > MAX_PLAYERS)
960 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
963 static void SDLCloseJoystick(int nr)
965 if (nr < 0 || nr > MAX_PLAYERS)
968 SDL_JoystickClose(sdl_joystick[nr]);
971 static boolean SDLCheckJoystickOpened(int nr)
973 if (nr < 0 || nr > MAX_PLAYERS)
976 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
979 void HandleJoystickEvent(Event *event)
983 case SDL_JOYAXISMOTION:
984 if (event->jaxis.axis < 2)
985 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
988 case SDL_JOYBUTTONDOWN:
989 if (event->jbutton.button < 2)
990 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
993 case SDL_JOYBUTTONUP:
994 if (event->jbutton.button < 2)
995 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1003 void SDLInitJoysticks()
1005 static boolean sdl_joystick_subsystem_initialized = FALSE;
1008 if (!sdl_joystick_subsystem_initialized)
1010 sdl_joystick_subsystem_initialized = TRUE;
1012 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1014 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1019 for (i=0; i<MAX_PLAYERS; i++)
1021 char *device_name = setup.input[i].joy.device_name;
1022 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1024 if (joystick_nr >= SDL_NumJoysticks())
1027 /* misuse joystick file descriptor variable to store joystick number */
1028 joystick.fd[i] = joystick_nr;
1030 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1031 if (SDLCheckJoystickOpened(joystick_nr))
1032 SDLCloseJoystick(joystick_nr);
1034 if (!setup.input[i].use_joystick)
1037 if (!SDLOpenJoystick(joystick_nr))
1039 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1043 joystick.status = JOYSTICK_ACTIVATED;
1047 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1049 if (nr < 0 || nr >= MAX_PLAYERS)
1053 *x = sdl_js_axis[nr][0];
1055 *y = sdl_js_axis[nr][1];
1058 *b1 = sdl_js_button[nr][0];
1060 *b2 = sdl_js_button[nr][1];
1065 #endif /* TARGET_SDL */