1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
21 #if defined(TARGET_SDL)
23 /* ========================================================================= */
25 /* ========================================================================= */
27 /* functions from SGE library */
28 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
30 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
31 static int fullscreen_width;
32 static int fullscreen_height;
33 static int fullscreen_xoffset;
34 static int fullscreen_yoffset;
35 static int video_xoffset;
36 static int video_yoffset;
38 static void setFullscreenParameters(char *fullscreen_mode_string)
40 struct ScreenModeInfo *fullscreen_mode;
43 fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
45 if (fullscreen_mode == NULL)
48 for (i = 0; video.fullscreen_modes[i].width != -1; i++)
50 if (fullscreen_mode->width == video.fullscreen_modes[i].width &&
51 fullscreen_mode->height == video.fullscreen_modes[i].height)
53 fullscreen_width = fullscreen_mode->width;
54 fullscreen_height = fullscreen_mode->height;
56 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
57 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
64 static void SDLSetWindowIcon(char *basename)
66 /* (setting the window icon on Mac OS X would replace the high-quality
67 dock icon with the currently smaller (and uglier) icon from file) */
69 #if !defined(PLATFORM_MACOSX)
70 char *filename = getCustomImageFilename(basename);
75 Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
80 if ((surface = IMG_Load(filename)) == NULL)
82 Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
87 /* set transparent color */
88 SDL_SetColorKey(surface, SDL_SRCCOLORKEY,
89 SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
91 SDL_WM_SetIcon(surface, NULL);
95 void SDLInitVideoDisplay(void)
97 if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
98 SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
100 SDL_putenv("SDL_VIDEO_CENTERED=1");
102 /* initialize SDL video */
103 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
104 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
106 /* set default SDL depth */
107 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
110 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
113 static int screen_xy[][2] =
123 /* default: normal game window size */
124 fullscreen_width = video.width;
125 fullscreen_height = video.height;
126 fullscreen_xoffset = 0;
127 fullscreen_yoffset = 0;
129 for (i = 0; screen_xy[i][0] != -1; i++)
131 if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
133 fullscreen_width = screen_xy[i][0];
134 fullscreen_height = screen_xy[i][1];
140 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
141 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
144 checked_free(video.fullscreen_modes);
146 video.fullscreen_modes = NULL;
147 video.fullscreen_mode_current = NULL;
150 /* get available hardware supported fullscreen modes */
151 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
155 /* no screen modes available => no fullscreen mode support */
156 video.fullscreen_available = FALSE;
158 else if (modes == (SDL_Rect **)-1)
160 /* fullscreen resolution is not restricted -- all resolutions available */
161 video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
163 /* use native video buffer size for fullscreen mode */
164 video.fullscreen_modes[0].width = video.width;
165 video.fullscreen_modes[0].height = video.height;
167 video.fullscreen_modes[1].width = -1;
168 video.fullscreen_modes[1].height = -1;
172 /* in this case, a certain number of screen modes is available */
175 for(i = 0; modes[i] != NULL; i++)
177 boolean found_mode = FALSE;
179 /* screen mode is smaller than video buffer size -- skip it */
180 if (modes[i]->w < video.width || modes[i]->h < video.height)
183 if (video.fullscreen_modes != NULL)
184 for (j = 0; video.fullscreen_modes[j].width != -1; j++)
185 if (modes[i]->w == video.fullscreen_modes[j].width &&
186 modes[i]->h == video.fullscreen_modes[j].height)
189 if (found_mode) /* screen mode already stored -- skip it */
192 /* new mode found; add it to list of available fullscreen modes */
196 video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
198 sizeof(struct ScreenModeInfo));
200 video.fullscreen_modes[num_modes - 1].width = modes[i]->w;
201 video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
203 video.fullscreen_modes[num_modes].width = -1;
204 video.fullscreen_modes[num_modes].height = -1;
209 /* no appropriate screen modes available => no fullscreen mode support */
210 video.fullscreen_available = FALSE;
214 /* set window icon */
215 SDLSetWindowIcon(program.sdl_icon_filename);
217 /* open SDL video output device (window or fullscreen mode) */
218 if (!SDLSetVideoMode(backbuffer, fullscreen))
219 Error(ERR_EXIT, "setting video mode failed");
221 /* set window and icon title */
222 SDL_WM_SetCaption(program.window_title, program.window_title);
224 /* SDL cannot directly draw to the visible video framebuffer like X11,
225 but always uses a backbuffer, which is then blitted to the visible
226 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
227 visible video framebuffer with 'SDL_Flip', if the hardware supports
228 this). Therefore do not use an additional backbuffer for drawing, but
229 use a symbolic buffer (distinguishable from the SDL backbuffer) called
230 'window', which indicates that the SDL backbuffer should be updated to
231 the visible video framebuffer when attempting to blit to it.
233 For convenience, it seems to be a good idea to create this symbolic
234 buffer 'window' at the same size as the SDL backbuffer. Although it
235 should never be drawn to directly, it would do no harm nevertheless. */
237 /* create additional (symbolic) buffer for double-buffering */
239 ReCreateBitmap(window, video.width, video.height, video.depth);
241 *window = CreateBitmap(video.width, video.height, video.depth);
245 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
247 boolean success = TRUE;
248 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
249 int surface_flags_window = SURFACE_FLAGS;
250 SDL_Surface *new_surface = NULL;
252 if (*backbuffer == NULL)
253 *backbuffer = CreateBitmapStruct();
255 /* (real bitmap might be larger in fullscreen mode with video offsets) */
256 (*backbuffer)->width = video.width;
257 (*backbuffer)->height = video.height;
259 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
261 setFullscreenParameters(setup.fullscreen_mode);
263 video_xoffset = fullscreen_xoffset;
264 video_yoffset = fullscreen_yoffset;
266 /* switch display to fullscreen mode, if available */
267 if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
268 video.depth, surface_flags_fullscreen))
271 /* switching display to fullscreen mode failed */
272 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
274 /* do not try it again */
275 video.fullscreen_available = FALSE;
281 (*backbuffer)->surface = new_surface;
283 video.fullscreen_enabled = TRUE;
284 video.fullscreen_mode_current = setup.fullscreen_mode;
290 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
295 /* switch display to window mode */
296 if ((new_surface = SDL_SetVideoMode(video.width, video.height,
297 video.depth, surface_flags_window))
300 /* switching display to window mode failed -- should not happen */
301 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
307 (*backbuffer)->surface = new_surface;
309 video.fullscreen_enabled = FALSE;
316 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
318 #if defined(PLATFORM_WIN32)
320 SDL_SysWMinfo wminfo;
323 SDL_VERSION(&wminfo.version);
324 SDL_GetWMInfo(&wminfo);
326 hwnd = wminfo.window;
328 DragAcceptFiles(hwnd, TRUE);
337 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
340 SDL_Surface *surface_tmp, *surface_native;
342 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
345 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
347 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
348 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
350 SDL_FreeSurface(surface_tmp);
352 new_bitmap->surface = surface_native;
355 void SDLFreeBitmapPointers(Bitmap *bitmap)
358 SDL_FreeSurface(bitmap->surface);
359 if (bitmap->surface_masked)
360 SDL_FreeSurface(bitmap->surface_masked);
361 bitmap->surface = NULL;
362 bitmap->surface_masked = NULL;
365 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
366 int src_x, int src_y, int width, int height,
367 int dst_x, int dst_y, int mask_mode)
369 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
370 SDL_Rect src_rect, dst_rect;
372 if (src_bitmap == backbuffer)
374 src_x += video_xoffset;
375 src_y += video_yoffset;
383 if (dst_bitmap == backbuffer || dst_bitmap == window)
385 dst_x += video_xoffset;
386 dst_y += video_yoffset;
394 if (src_bitmap != backbuffer || dst_bitmap != window)
395 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
396 src_bitmap->surface_masked : src_bitmap->surface),
397 &src_rect, real_dst_bitmap->surface, &dst_rect);
399 if (dst_bitmap == window)
400 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
403 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
406 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
409 if (dst_bitmap == backbuffer || dst_bitmap == window)
420 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
422 if (dst_bitmap == window)
423 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
426 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
427 int fade_mode, int fade_delay, int post_delay,
428 void (*draw_border_function)(void))
430 static boolean initialization_needed = TRUE;
431 static SDL_Surface *surface_source = NULL;
432 static SDL_Surface *surface_target = NULL;
433 static SDL_Surface *surface_black = NULL;
434 SDL_Surface *surface_screen = backbuffer->surface;
435 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
436 SDL_Rect src_rect, dst_rect;
437 int src_x = x, src_y = y;
438 int dst_x = x, dst_y = y;
439 unsigned int time_last, time_current;
441 /* check if screen size has changed */
442 if (surface_source != NULL && (video.width != surface_source->w ||
443 video.height != surface_source->h))
445 SDL_FreeSurface(surface_source);
446 SDL_FreeSurface(surface_target);
447 SDL_FreeSurface(surface_black);
449 initialization_needed = TRUE;
457 dst_x += video_xoffset;
458 dst_y += video_yoffset;
462 dst_rect.w = width; /* (ignored) */
463 dst_rect.h = height; /* (ignored) */
465 if (initialization_needed)
467 unsigned int flags = SDL_SRCALPHA;
469 /* use same surface type as screen surface */
470 if ((surface_screen->flags & SDL_HWSURFACE))
471 flags |= SDL_HWSURFACE;
473 flags |= SDL_SWSURFACE;
475 /* create surface for temporary copy of screen buffer (source) */
476 if ((surface_source =
477 SDL_CreateRGBSurface(flags,
480 surface_screen->format->BitsPerPixel,
481 surface_screen->format->Rmask,
482 surface_screen->format->Gmask,
483 surface_screen->format->Bmask,
484 surface_screen->format->Amask)) == NULL)
485 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
487 /* create surface for cross-fading screen buffer (target) */
488 if ((surface_target =
489 SDL_CreateRGBSurface(flags,
492 surface_screen->format->BitsPerPixel,
493 surface_screen->format->Rmask,
494 surface_screen->format->Gmask,
495 surface_screen->format->Bmask,
496 surface_screen->format->Amask)) == NULL)
497 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
499 /* create black surface for fading from/to black */
501 SDL_CreateRGBSurface(flags,
504 surface_screen->format->BitsPerPixel,
505 surface_screen->format->Rmask,
506 surface_screen->format->Gmask,
507 surface_screen->format->Bmask,
508 surface_screen->format->Amask)) == NULL)
509 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
511 /* completely fill the surface with black color pixels */
512 SDL_FillRect(surface_black, NULL,
513 SDL_MapRGB(surface_screen->format, 0, 0, 0));
515 initialization_needed = FALSE;
518 /* copy source and target surfaces to temporary surfaces for fading */
519 if (fade_mode & FADE_TYPE_TRANSFORM)
521 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
522 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
524 else if (fade_mode & FADE_TYPE_FADE_IN)
526 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
527 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
529 else /* FADE_TYPE_FADE_OUT */
531 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
532 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
535 time_current = SDL_GetTicks();
537 if (fade_mode == FADE_MODE_MELT)
539 boolean done = FALSE;
541 int melt_columns = width / melt_pixels;
542 int ypos[melt_columns];
543 int max_steps = height / 8 + 32;
548 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
549 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
551 ypos[0] = -GetSimpleRandom(16);
553 for (i = 1 ; i < melt_columns; i++)
555 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
557 ypos[i] = ypos[i - 1] + r;
570 time_last = time_current;
571 time_current = SDL_GetTicks();
572 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
573 steps_final = MIN(MAX(0, steps), max_steps);
577 done = (steps_done >= steps_final);
579 for (i = 0 ; i < melt_columns; i++)
587 else if (ypos[i] < height)
592 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
594 if (ypos[i] + dy >= height)
595 dy = height - ypos[i];
597 /* copy part of (appearing) target surface to upper area */
598 src_rect.x = src_x + i * melt_pixels;
599 // src_rect.y = src_y + ypos[i];
601 src_rect.w = melt_pixels;
603 src_rect.h = ypos[i] + dy;
605 dst_rect.x = dst_x + i * melt_pixels;
606 // dst_rect.y = dst_y + ypos[i];
609 if (steps_done >= steps_final)
610 SDL_BlitSurface(surface_target, &src_rect,
611 surface_screen, &dst_rect);
615 /* copy part of (disappearing) source surface to lower area */
616 src_rect.x = src_x + i * melt_pixels;
618 src_rect.w = melt_pixels;
619 src_rect.h = height - ypos[i];
621 dst_rect.x = dst_x + i * melt_pixels;
622 dst_rect.y = dst_y + ypos[i];
624 if (steps_done >= steps_final)
625 SDL_BlitSurface(surface_source, &src_rect,
626 surface_screen, &dst_rect);
632 src_rect.x = src_x + i * melt_pixels;
634 src_rect.w = melt_pixels;
637 dst_rect.x = dst_x + i * melt_pixels;
640 if (steps_done >= steps_final)
641 SDL_BlitSurface(surface_target, &src_rect,
642 surface_screen, &dst_rect);
646 if (steps_done >= steps_final)
648 if (draw_border_function != NULL)
649 draw_border_function();
651 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
660 for (alpha = 0.0; alpha < 255.0;)
662 time_last = time_current;
663 time_current = SDL_GetTicks();
664 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
665 alpha_final = MIN(MAX(0, alpha), 255);
667 /* draw existing (source) image to screen buffer */
668 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
670 /* draw new (target) image to screen buffer using alpha blending */
671 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
672 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
674 if (draw_border_function != NULL)
675 draw_border_function();
678 /* only update the region of the screen that is affected from fading */
679 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
681 SDL_Flip(surface_screen);
689 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
690 int to_x, int to_y, Uint32 color)
692 SDL_Surface *surface = dst_bitmap->surface;
696 swap_numbers(&from_x, &to_x);
699 swap_numbers(&from_y, &to_y);
703 rect.w = (to_x - from_x + 1);
704 rect.h = (to_y - from_y + 1);
706 if (dst_bitmap == backbuffer || dst_bitmap == window)
708 rect.x += video_xoffset;
709 rect.y += video_yoffset;
712 SDL_FillRect(surface, &rect, color);
715 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
716 int to_x, int to_y, Uint32 color)
718 if (dst_bitmap == backbuffer || dst_bitmap == window)
720 from_x += video_xoffset;
721 from_y += video_yoffset;
722 to_x += video_xoffset;
723 to_y += video_yoffset;
726 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
730 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
731 int num_points, Uint32 color)
736 for (i = 0; i < num_points - 1; i++)
738 for (x = 0; x < line_width; x++)
740 for (y = 0; y < line_width; y++)
742 int dx = x - line_width / 2;
743 int dy = y - line_width / 2;
745 if ((x == 0 && y == 0) ||
746 (x == 0 && y == line_width - 1) ||
747 (x == line_width - 1 && y == 0) ||
748 (x == line_width - 1 && y == line_width - 1))
751 sge_Line(surface, points[i].x + dx, points[i].y + dy,
752 points[i+1].x + dx, points[i+1].y + dy, color);
759 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
761 SDL_Surface *surface = src_bitmap->surface;
763 if (src_bitmap == backbuffer || src_bitmap == window)
769 switch (surface->format->BytesPerPixel)
771 case 1: /* assuming 8-bpp */
773 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
777 case 2: /* probably 15-bpp or 16-bpp */
779 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
783 case 3: /* slow 24-bpp mode; usually not used */
785 /* does this work? */
786 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
790 shift = surface->format->Rshift;
791 color |= *(pix + shift / 8) >> shift;
792 shift = surface->format->Gshift;
793 color |= *(pix + shift / 8) >> shift;
794 shift = surface->format->Bshift;
795 color |= *(pix + shift / 8) >> shift;
801 case 4: /* probably 32-bpp */
803 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
812 /* ========================================================================= */
813 /* The following functions were taken from the SGE library */
814 /* (SDL Graphics Extension Library) by Anders Lindström */
815 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
816 /* ========================================================================= */
818 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
820 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
822 switch (surface->format->BytesPerPixel)
827 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
833 /* Probably 15-bpp or 16-bpp */
834 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
840 /* Slow 24-bpp mode, usually not used */
844 /* Gack - slow, but endian correct */
845 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
846 shift = surface->format->Rshift;
847 *(pix+shift/8) = color>>shift;
848 shift = surface->format->Gshift;
849 *(pix+shift/8) = color>>shift;
850 shift = surface->format->Bshift;
851 *(pix+shift/8) = color>>shift;
857 /* Probably 32-bpp */
858 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
865 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
866 Uint8 R, Uint8 G, Uint8 B)
868 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
871 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
873 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
876 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
878 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
881 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
886 /* Gack - slow, but endian correct */
887 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
888 shift = surface->format->Rshift;
889 *(pix+shift/8) = color>>shift;
890 shift = surface->format->Gshift;
891 *(pix+shift/8) = color>>shift;
892 shift = surface->format->Bshift;
893 *(pix+shift/8) = color>>shift;
896 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
898 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
901 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
903 switch (dest->format->BytesPerPixel)
906 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
910 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
914 _PutPixel24(dest,x,y,color);
918 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
923 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
925 if (SDL_MUSTLOCK(surface))
927 if (SDL_LockSurface(surface) < 0)
933 _PutPixel(surface, x, y, color);
935 if (SDL_MUSTLOCK(surface))
937 SDL_UnlockSurface(surface);
941 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
942 Uint8 r, Uint8 g, Uint8 b)
944 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
947 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
949 if (y >= 0 && y <= dest->h - 1)
951 switch (dest->format->BytesPerPixel)
954 return y*dest->pitch;
958 return y*dest->pitch/2;
962 return y*dest->pitch;
966 return y*dest->pitch/4;
974 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
976 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
978 switch (surface->format->BytesPerPixel)
983 *((Uint8 *)surface->pixels + ypitch + x) = color;
989 /* Probably 15-bpp or 16-bpp */
990 *((Uint16 *)surface->pixels + ypitch + x) = color;
996 /* Slow 24-bpp mode, usually not used */
1000 /* Gack - slow, but endian correct */
1001 pix = (Uint8 *)surface->pixels + ypitch + x*3;
1002 shift = surface->format->Rshift;
1003 *(pix+shift/8) = color>>shift;
1004 shift = surface->format->Gshift;
1005 *(pix+shift/8) = color>>shift;
1006 shift = surface->format->Bshift;
1007 *(pix+shift/8) = color>>shift;
1013 /* Probably 32-bpp */
1014 *((Uint32 *)surface->pixels + ypitch + x) = color;
1021 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1026 if (SDL_MUSTLOCK(Surface))
1028 if (SDL_LockSurface(Surface) < 0)
1041 /* Do the clipping */
1042 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1046 if (x2 > Surface->w - 1)
1047 x2 = Surface->w - 1;
1054 SDL_FillRect(Surface, &l, Color);
1056 if (SDL_MUSTLOCK(Surface))
1058 SDL_UnlockSurface(Surface);
1062 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1063 Uint8 R, Uint8 G, Uint8 B)
1065 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1068 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1079 /* Do the clipping */
1080 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1084 if (x2 > Surface->w - 1)
1085 x2 = Surface->w - 1;
1092 SDL_FillRect(Surface, &l, Color);
1095 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1100 if (SDL_MUSTLOCK(Surface))
1102 if (SDL_LockSurface(Surface) < 0)
1115 /* Do the clipping */
1116 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1120 if (y2 > Surface->h - 1)
1121 y2 = Surface->h - 1;
1128 SDL_FillRect(Surface, &l, Color);
1130 if (SDL_MUSTLOCK(Surface))
1132 SDL_UnlockSurface(Surface);
1136 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1137 Uint8 R, Uint8 G, Uint8 B)
1139 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1142 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1153 /* Do the clipping */
1154 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1158 if (y2 > Surface->h - 1)
1159 y2 = Surface->h - 1;
1166 SDL_FillRect(Surface, &l, Color);
1169 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1170 Sint16 x2, Sint16 y2, Uint32 Color,
1171 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1174 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1179 sdx = (dx < 0) ? -1 : 1;
1180 sdy = (dy < 0) ? -1 : 1;
1192 for (x = 0; x < dx; x++)
1194 Callback(Surface, px, py, Color);
1208 for (y = 0; y < dy; y++)
1210 Callback(Surface, px, py, Color);
1224 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
1225 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
1226 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1229 sge_DoLine(Surface, X1, Y1, X2, Y2,
1230 SDL_MapRGB(Surface->format, R, G, B), Callback);
1233 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
1236 if (SDL_MUSTLOCK(Surface))
1238 if (SDL_LockSurface(Surface) < 0)
1243 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
1245 /* unlock the display */
1246 if (SDL_MUSTLOCK(Surface))
1248 SDL_UnlockSurface(Surface);
1252 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
1253 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1255 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
1258 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
1260 if (dst_bitmap == backbuffer || dst_bitmap == window)
1266 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
1271 -----------------------------------------------------------------------------
1272 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
1273 -----------------------------------------------------------------------------
1276 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
1277 int width, int height, Uint32 color)
1281 for (y = src_y; y < src_y + height; y++)
1283 for (x = src_x; x < src_x + width; x++)
1285 Uint32 pixel = SDLGetPixel(bitmap, x, y);
1287 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
1292 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1293 int src_x, int src_y, int width, int height,
1294 int dst_x, int dst_y)
1298 for (y = 0; y < height; y++)
1300 for (x = 0; x < width; x++)
1302 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
1304 if (pixel != BLACK_PIXEL)
1305 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
1311 /* ========================================================================= */
1312 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
1313 /* (Rotozoomer) by Andreas Schiffler */
1314 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
1315 /* ========================================================================= */
1318 -----------------------------------------------------------------------------
1321 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
1322 -----------------------------------------------------------------------------
1333 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
1336 tColorRGBA *sp, *csp, *dp;
1340 sp = csp = (tColorRGBA *) src->pixels;
1341 dp = (tColorRGBA *) dst->pixels;
1342 sgap = src->pitch - src->w * 4;
1343 dgap = dst->pitch - dst->w * 4;
1345 for (y = 0; y < dst->h; y++)
1349 for (x = 0; x < dst->w; x++)
1351 tColorRGBA *sp0 = sp;
1352 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
1353 tColorRGBA *sp00 = &sp0[0];
1354 tColorRGBA *sp01 = &sp0[1];
1355 tColorRGBA *sp10 = &sp1[0];
1356 tColorRGBA *sp11 = &sp1[1];
1359 /* create new color pixel from all four source color pixels */
1360 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
1361 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
1362 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
1363 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
1368 /* advance source pointers */
1371 /* advance destination pointer */
1375 /* advance source pointer */
1376 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
1378 /* advance destination pointers */
1379 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1385 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1387 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1388 tColorRGBA *sp, *csp, *dp;
1391 /* use specialized zoom function when scaling down to exactly half size */
1392 if (src->w == 2 * dst->w &&
1393 src->h == 2 * dst->h)
1394 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
1396 /* variable setup */
1397 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1398 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1400 /* allocate memory for row increments */
1401 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1402 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1404 /* precalculate row increments */
1407 for (x = 0; x <= dst->w; x++)
1417 for (y = 0; y <= dst->h; y++)
1426 sp = csp = (tColorRGBA *) src->pixels;
1427 dp = (tColorRGBA *) dst->pixels;
1428 sgap = src->pitch - src->w * 4;
1429 dgap = dst->pitch - dst->w * 4;
1432 for (y = 0; y < dst->h; y++)
1437 for (x = 0; x < dst->w; x++)
1442 /* advance source pointers */
1444 sp += (*csax >> 16);
1446 /* advance destination pointer */
1450 /* advance source pointer */
1452 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1454 /* advance destination pointers */
1455 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1465 -----------------------------------------------------------------------------
1468 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1469 -----------------------------------------------------------------------------
1472 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1474 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1475 Uint8 *sp, *dp, *csp;
1478 /* variable setup */
1479 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1480 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1482 /* allocate memory for row increments */
1483 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1484 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1486 /* precalculate row increments */
1489 for (x = 0; x < dst->w; x++)
1492 *csax = (csx >> 16);
1499 for (y = 0; y < dst->h; y++)
1502 *csay = (csy >> 16);
1509 for (x = 0; x < dst->w; x++)
1517 for (y = 0; y < dst->h; y++)
1524 sp = csp = (Uint8 *) src->pixels;
1525 dp = (Uint8 *) dst->pixels;
1526 dgap = dst->pitch - dst->w;
1530 for (y = 0; y < dst->h; y++)
1534 for (x = 0; x < dst->w; x++)
1539 /* advance source pointers */
1543 /* advance destination pointer */
1547 /* advance source pointer (for row) */
1548 csp += ((*csay) * src->pitch);
1551 /* advance destination pointers */
1562 -----------------------------------------------------------------------------
1565 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1566 'zoomx' and 'zoomy' are scaling factors for width and height.
1567 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1568 into a 32bit RGBA format on the fly.
1569 -----------------------------------------------------------------------------
1572 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1574 SDL_Surface *zoom_src = NULL;
1575 SDL_Surface *zoom_dst = NULL;
1576 boolean is_converted = FALSE;
1583 /* determine if source surface is 32 bit or 8 bit */
1584 is_32bit = (src->format->BitsPerPixel == 32);
1586 if (is_32bit || src->format->BitsPerPixel == 8)
1588 /* use source surface 'as is' */
1593 /* new source surface is 32 bit with a defined RGB ordering */
1594 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1595 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1596 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1598 is_converted = TRUE;
1601 /* allocate surface to completely contain the zoomed surface */
1604 /* target surface is 32 bit with source RGBA/ABGR ordering */
1605 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1606 zoom_src->format->Rmask,
1607 zoom_src->format->Gmask,
1608 zoom_src->format->Bmask, 0);
1612 /* target surface is 8 bit */
1613 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1617 /* lock source surface */
1618 SDL_LockSurface(zoom_src);
1620 /* check which kind of surface we have */
1623 /* call the 32 bit transformation routine to do the zooming */
1624 zoomSurfaceRGBA(zoom_src, zoom_dst);
1629 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1630 zoom_dst->format->palette->colors[i] =
1631 zoom_src->format->palette->colors[i];
1632 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1634 /* call the 8 bit transformation routine to do the zooming */
1635 zoomSurfaceY(zoom_src, zoom_dst);
1638 /* unlock source surface */
1639 SDL_UnlockSurface(zoom_src);
1641 /* free temporary surface */
1643 SDL_FreeSurface(zoom_src);
1645 /* return destination surface */
1649 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1651 SDL_Surface *sdl_surface_tmp;
1652 int dst_width = dst_bitmap->width;
1653 int dst_height = dst_bitmap->height;
1655 /* throw away old destination surface */
1656 SDL_FreeSurface(dst_bitmap->surface);
1658 /* create zoomed temporary surface from source surface */
1659 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1661 /* create native format destination surface from zoomed temporary surface */
1662 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1664 /* free temporary surface */
1665 SDL_FreeSurface(sdl_surface_tmp);
1669 /* ========================================================================= */
1670 /* load image to bitmap */
1671 /* ========================================================================= */
1673 Bitmap *SDLLoadImage(char *filename)
1675 Bitmap *new_bitmap = CreateBitmapStruct();
1676 SDL_Surface *sdl_image_tmp;
1678 /* load image to temporary surface */
1679 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1681 SetError("IMG_Load(): %s", SDL_GetError());
1686 UPDATE_BUSY_STATE();
1688 /* create native non-transparent surface for current image */
1689 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1691 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1696 UPDATE_BUSY_STATE();
1698 /* create native transparent surface for current image */
1699 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1700 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1701 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1703 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1708 UPDATE_BUSY_STATE();
1710 /* free temporary surface */
1711 SDL_FreeSurface(sdl_image_tmp);
1713 new_bitmap->width = new_bitmap->surface->w;
1714 new_bitmap->height = new_bitmap->surface->h;
1720 /* ------------------------------------------------------------------------- */
1721 /* custom cursor fuctions */
1722 /* ------------------------------------------------------------------------- */
1724 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1726 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1727 cursor_info->width, cursor_info->height,
1728 cursor_info->hot_x, cursor_info->hot_y);
1731 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1733 static struct MouseCursorInfo *last_cursor_info = NULL;
1734 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1735 static SDL_Cursor *cursor_default = NULL;
1736 static SDL_Cursor *cursor_current = NULL;
1738 /* if invoked for the first time, store the SDL default cursor */
1739 if (cursor_default == NULL)
1740 cursor_default = SDL_GetCursor();
1742 /* only create new cursor if cursor info (custom only) has changed */
1743 if (cursor_info != NULL && cursor_info != last_cursor_info)
1745 cursor_current = create_cursor(cursor_info);
1746 last_cursor_info = cursor_info;
1749 /* only set new cursor if cursor info (custom or NULL) has changed */
1750 if (cursor_info != last_cursor_info2)
1751 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1753 last_cursor_info2 = cursor_info;
1757 /* ========================================================================= */
1758 /* audio functions */
1759 /* ========================================================================= */
1761 void SDLOpenAudio(void)
1763 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
1764 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1766 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1768 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1772 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1773 AUDIO_NUM_CHANNELS_STEREO,
1774 setup.system.audio_fragment_size) < 0)
1776 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1780 audio.sound_available = TRUE;
1781 audio.music_available = TRUE;
1782 audio.loops_available = TRUE;
1783 audio.sound_enabled = TRUE;
1785 /* set number of available mixer channels */
1786 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1787 audio.music_channel = MUSIC_CHANNEL;
1788 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1790 Mixer_InitChannels();
1793 void SDLCloseAudio(void)
1796 Mix_HaltChannel(-1);
1799 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1803 /* ========================================================================= */
1804 /* event functions */
1805 /* ========================================================================= */
1807 void SDLNextEvent(Event *event)
1809 SDL_WaitEvent(event);
1811 if (event->type == EVENT_BUTTONPRESS ||
1812 event->type == EVENT_BUTTONRELEASE)
1814 if (((ButtonEvent *)event)->x > video_xoffset)
1815 ((ButtonEvent *)event)->x -= video_xoffset;
1817 ((ButtonEvent *)event)->x = 0;
1818 if (((ButtonEvent *)event)->y > video_yoffset)
1819 ((ButtonEvent *)event)->y -= video_yoffset;
1821 ((ButtonEvent *)event)->y = 0;
1823 else if (event->type == EVENT_MOTIONNOTIFY)
1825 if (((MotionEvent *)event)->x > video_xoffset)
1826 ((MotionEvent *)event)->x -= video_xoffset;
1828 ((MotionEvent *)event)->x = 0;
1829 if (((MotionEvent *)event)->y > video_yoffset)
1830 ((MotionEvent *)event)->y -= video_yoffset;
1832 ((MotionEvent *)event)->y = 0;
1836 void SDLHandleWindowManagerEvent(Event *event)
1838 #if defined(PLATFORM_WIN32)
1839 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
1840 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
1842 if (syswmmsg->msg == WM_DROPFILES)
1844 HDROP hdrop = (HDROP)syswmmsg->wParam;
1847 printf("::: SDL_SYSWMEVENT:\n");
1849 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
1851 for (i = 0; i < num_files; i++)
1853 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
1854 char buffer[buffer_len + 1];
1856 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
1858 printf("::: - '%s'\n", buffer);
1861 DragFinish((HDROP)syswmmsg->wParam);
1867 /* ========================================================================= */
1868 /* joystick functions */
1869 /* ========================================================================= */
1871 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1872 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1873 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1875 static boolean SDLOpenJoystick(int nr)
1877 if (nr < 0 || nr > MAX_PLAYERS)
1880 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1883 static void SDLCloseJoystick(int nr)
1885 if (nr < 0 || nr > MAX_PLAYERS)
1888 SDL_JoystickClose(sdl_joystick[nr]);
1891 static boolean SDLCheckJoystickOpened(int nr)
1893 if (nr < 0 || nr > MAX_PLAYERS)
1896 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1899 void HandleJoystickEvent(Event *event)
1903 case SDL_JOYAXISMOTION:
1904 if (event->jaxis.axis < 2)
1905 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1908 case SDL_JOYBUTTONDOWN:
1909 if (event->jbutton.button < 2)
1910 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1913 case SDL_JOYBUTTONUP:
1914 if (event->jbutton.button < 2)
1915 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1923 void SDLInitJoysticks()
1925 static boolean sdl_joystick_subsystem_initialized = FALSE;
1926 boolean print_warning = !sdl_joystick_subsystem_initialized;
1929 if (!sdl_joystick_subsystem_initialized)
1931 sdl_joystick_subsystem_initialized = TRUE;
1933 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1935 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1940 for (i = 0; i < MAX_PLAYERS; i++)
1942 /* get configured joystick for this player */
1943 char *device_name = setup.input[i].joy.device_name;
1944 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1946 if (joystick_nr >= SDL_NumJoysticks())
1948 if (setup.input[i].use_joystick && print_warning)
1949 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
1954 /* misuse joystick file descriptor variable to store joystick number */
1955 joystick.fd[i] = joystick_nr;
1957 if (joystick_nr == -1)
1960 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1961 if (SDLCheckJoystickOpened(joystick_nr))
1962 SDLCloseJoystick(joystick_nr);
1964 if (!setup.input[i].use_joystick)
1967 if (!SDLOpenJoystick(joystick_nr))
1970 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1975 joystick.status = JOYSTICK_ACTIVATED;
1979 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1981 if (nr < 0 || nr >= MAX_PLAYERS)
1985 *x = sdl_js_axis[nr][0];
1987 *y = sdl_js_axis[nr][1];
1990 *b1 = sdl_js_button[nr][0];
1992 *b2 = sdl_js_button[nr][1];
1997 #endif /* TARGET_SDL */