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;
1343 sp = csp = (tColorRGBA *) src->pixels;
1344 dp = (tColorRGBA *) dst->pixels;
1346 sgap = src->pitch - src->w * 4;
1348 dgap = dst->pitch - dst->w * 4;
1350 for (y = 0; y < dst->h; y++)
1354 for (x = 0; x < dst->w; x++)
1356 tColorRGBA *sp0 = sp;
1357 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
1358 tColorRGBA *sp00 = &sp0[0];
1359 tColorRGBA *sp01 = &sp0[1];
1360 tColorRGBA *sp10 = &sp1[0];
1361 tColorRGBA *sp11 = &sp1[1];
1364 /* create new color pixel from all four source color pixels */
1365 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
1366 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
1367 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
1368 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
1373 /* advance source pointers */
1376 /* advance destination pointer */
1380 /* advance source pointer */
1381 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
1383 /* advance destination pointers */
1384 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1390 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1392 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1393 tColorRGBA *sp, *csp, *dp;
1399 /* use specialized zoom function when scaling down to exactly half size */
1400 if (src->w == 2 * dst->w &&
1401 src->h == 2 * dst->h)
1402 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
1404 /* variable setup */
1405 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1406 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1408 /* allocate memory for row increments */
1409 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1410 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1412 /* precalculate row increments */
1415 for (x = 0; x <= dst->w; x++)
1425 for (y = 0; y <= dst->h; y++)
1434 sp = csp = (tColorRGBA *) src->pixels;
1435 dp = (tColorRGBA *) dst->pixels;
1437 sgap = src->pitch - src->w * 4;
1439 dgap = dst->pitch - dst->w * 4;
1442 for (y = 0; y < dst->h; y++)
1447 for (x = 0; x < dst->w; x++)
1452 /* advance source pointers */
1454 sp += (*csax >> 16);
1456 /* advance destination pointer */
1460 /* advance source pointer */
1462 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1464 /* advance destination pointers */
1465 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1475 -----------------------------------------------------------------------------
1478 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1479 -----------------------------------------------------------------------------
1482 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1484 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1485 Uint8 *sp, *dp, *csp;
1488 /* variable setup */
1489 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1490 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1492 /* allocate memory for row increments */
1493 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1494 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1496 /* precalculate row increments */
1499 for (x = 0; x < dst->w; x++)
1502 *csax = (csx >> 16);
1509 for (y = 0; y < dst->h; y++)
1512 *csay = (csy >> 16);
1519 for (x = 0; x < dst->w; x++)
1527 for (y = 0; y < dst->h; y++)
1534 sp = csp = (Uint8 *) src->pixels;
1535 dp = (Uint8 *) dst->pixels;
1536 dgap = dst->pitch - dst->w;
1540 for (y = 0; y < dst->h; y++)
1544 for (x = 0; x < dst->w; x++)
1549 /* advance source pointers */
1553 /* advance destination pointer */
1557 /* advance source pointer (for row) */
1558 csp += ((*csay) * src->pitch);
1561 /* advance destination pointers */
1572 -----------------------------------------------------------------------------
1575 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1576 'zoomx' and 'zoomy' are scaling factors for width and height.
1577 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1578 into a 32bit RGBA format on the fly.
1579 -----------------------------------------------------------------------------
1582 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1584 SDL_Surface *zoom_src = NULL;
1585 SDL_Surface *zoom_dst = NULL;
1586 boolean is_converted = FALSE;
1593 /* determine if source surface is 32 bit or 8 bit */
1594 is_32bit = (src->format->BitsPerPixel == 32);
1596 if (is_32bit || src->format->BitsPerPixel == 8)
1598 /* use source surface 'as is' */
1603 /* new source surface is 32 bit with a defined RGB ordering */
1604 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1605 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1606 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1608 is_converted = TRUE;
1611 /* allocate surface to completely contain the zoomed surface */
1614 /* target surface is 32 bit with source RGBA/ABGR ordering */
1615 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1616 zoom_src->format->Rmask,
1617 zoom_src->format->Gmask,
1618 zoom_src->format->Bmask, 0);
1622 /* target surface is 8 bit */
1623 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1627 /* lock source surface */
1628 SDL_LockSurface(zoom_src);
1630 /* check which kind of surface we have */
1633 /* call the 32 bit transformation routine to do the zooming */
1634 zoomSurfaceRGBA(zoom_src, zoom_dst);
1639 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1640 zoom_dst->format->palette->colors[i] =
1641 zoom_src->format->palette->colors[i];
1642 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1644 /* call the 8 bit transformation routine to do the zooming */
1645 zoomSurfaceY(zoom_src, zoom_dst);
1648 /* unlock source surface */
1649 SDL_UnlockSurface(zoom_src);
1651 /* free temporary surface */
1653 SDL_FreeSurface(zoom_src);
1655 /* return destination surface */
1659 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1661 SDL_Surface *sdl_surface_tmp;
1662 int dst_width = dst_bitmap->width;
1663 int dst_height = dst_bitmap->height;
1665 /* throw away old destination surface */
1666 SDL_FreeSurface(dst_bitmap->surface);
1668 /* create zoomed temporary surface from source surface */
1669 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1671 /* create native format destination surface from zoomed temporary surface */
1672 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1674 /* free temporary surface */
1675 SDL_FreeSurface(sdl_surface_tmp);
1679 /* ========================================================================= */
1680 /* load image to bitmap */
1681 /* ========================================================================= */
1683 Bitmap *SDLLoadImage(char *filename)
1685 Bitmap *new_bitmap = CreateBitmapStruct();
1686 SDL_Surface *sdl_image_tmp;
1688 /* load image to temporary surface */
1689 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1691 SetError("IMG_Load(): %s", SDL_GetError());
1696 UPDATE_BUSY_STATE();
1698 /* create native non-transparent surface for current image */
1699 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1701 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1706 UPDATE_BUSY_STATE();
1708 /* create native transparent surface for current image */
1709 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1710 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1711 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1713 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1718 UPDATE_BUSY_STATE();
1720 /* free temporary surface */
1721 SDL_FreeSurface(sdl_image_tmp);
1723 new_bitmap->width = new_bitmap->surface->w;
1724 new_bitmap->height = new_bitmap->surface->h;
1730 /* ------------------------------------------------------------------------- */
1731 /* custom cursor fuctions */
1732 /* ------------------------------------------------------------------------- */
1734 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1736 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1737 cursor_info->width, cursor_info->height,
1738 cursor_info->hot_x, cursor_info->hot_y);
1741 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1743 static struct MouseCursorInfo *last_cursor_info = NULL;
1744 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1745 static SDL_Cursor *cursor_default = NULL;
1746 static SDL_Cursor *cursor_current = NULL;
1748 /* if invoked for the first time, store the SDL default cursor */
1749 if (cursor_default == NULL)
1750 cursor_default = SDL_GetCursor();
1752 /* only create new cursor if cursor info (custom only) has changed */
1753 if (cursor_info != NULL && cursor_info != last_cursor_info)
1755 cursor_current = create_cursor(cursor_info);
1756 last_cursor_info = cursor_info;
1759 /* only set new cursor if cursor info (custom or NULL) has changed */
1760 if (cursor_info != last_cursor_info2)
1761 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1763 last_cursor_info2 = cursor_info;
1767 /* ========================================================================= */
1768 /* audio functions */
1769 /* ========================================================================= */
1771 void SDLOpenAudio(void)
1773 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
1774 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1776 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1778 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1782 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1783 AUDIO_NUM_CHANNELS_STEREO,
1784 setup.system.audio_fragment_size) < 0)
1786 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1790 audio.sound_available = TRUE;
1791 audio.music_available = TRUE;
1792 audio.loops_available = TRUE;
1793 audio.sound_enabled = TRUE;
1795 /* set number of available mixer channels */
1796 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1797 audio.music_channel = MUSIC_CHANNEL;
1798 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1800 Mixer_InitChannels();
1803 void SDLCloseAudio(void)
1806 Mix_HaltChannel(-1);
1809 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1813 /* ========================================================================= */
1814 /* event functions */
1815 /* ========================================================================= */
1817 void SDLNextEvent(Event *event)
1819 SDL_WaitEvent(event);
1821 if (event->type == EVENT_BUTTONPRESS ||
1822 event->type == EVENT_BUTTONRELEASE)
1824 if (((ButtonEvent *)event)->x > video_xoffset)
1825 ((ButtonEvent *)event)->x -= video_xoffset;
1827 ((ButtonEvent *)event)->x = 0;
1828 if (((ButtonEvent *)event)->y > video_yoffset)
1829 ((ButtonEvent *)event)->y -= video_yoffset;
1831 ((ButtonEvent *)event)->y = 0;
1833 else if (event->type == EVENT_MOTIONNOTIFY)
1835 if (((MotionEvent *)event)->x > video_xoffset)
1836 ((MotionEvent *)event)->x -= video_xoffset;
1838 ((MotionEvent *)event)->x = 0;
1839 if (((MotionEvent *)event)->y > video_yoffset)
1840 ((MotionEvent *)event)->y -= video_yoffset;
1842 ((MotionEvent *)event)->y = 0;
1846 void SDLHandleWindowManagerEvent(Event *event)
1848 #if defined(PLATFORM_WIN32)
1849 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
1850 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
1852 if (syswmmsg->msg == WM_DROPFILES)
1854 HDROP hdrop = (HDROP)syswmmsg->wParam;
1857 printf("::: SDL_SYSWMEVENT:\n");
1859 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
1861 for (i = 0; i < num_files; i++)
1863 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
1864 char buffer[buffer_len + 1];
1866 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
1868 printf("::: - '%s'\n", buffer);
1871 DragFinish((HDROP)syswmmsg->wParam);
1877 /* ========================================================================= */
1878 /* joystick functions */
1879 /* ========================================================================= */
1881 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1882 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1883 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1885 static boolean SDLOpenJoystick(int nr)
1887 if (nr < 0 || nr > MAX_PLAYERS)
1890 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1893 static void SDLCloseJoystick(int nr)
1895 if (nr < 0 || nr > MAX_PLAYERS)
1898 SDL_JoystickClose(sdl_joystick[nr]);
1901 static boolean SDLCheckJoystickOpened(int nr)
1903 if (nr < 0 || nr > MAX_PLAYERS)
1906 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1909 void HandleJoystickEvent(Event *event)
1913 case SDL_JOYAXISMOTION:
1914 if (event->jaxis.axis < 2)
1915 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1918 case SDL_JOYBUTTONDOWN:
1919 if (event->jbutton.button < 2)
1920 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1923 case SDL_JOYBUTTONUP:
1924 if (event->jbutton.button < 2)
1925 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1933 void SDLInitJoysticks()
1935 static boolean sdl_joystick_subsystem_initialized = FALSE;
1936 boolean print_warning = !sdl_joystick_subsystem_initialized;
1939 if (!sdl_joystick_subsystem_initialized)
1941 sdl_joystick_subsystem_initialized = TRUE;
1943 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1945 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1950 for (i = 0; i < MAX_PLAYERS; i++)
1952 /* get configured joystick for this player */
1953 char *device_name = setup.input[i].joy.device_name;
1954 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1956 if (joystick_nr >= SDL_NumJoysticks())
1958 if (setup.input[i].use_joystick && print_warning)
1959 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
1964 /* misuse joystick file descriptor variable to store joystick number */
1965 joystick.fd[i] = joystick_nr;
1967 if (joystick_nr == -1)
1970 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1971 if (SDLCheckJoystickOpened(joystick_nr))
1972 SDLCloseJoystick(joystick_nr);
1974 if (!setup.input[i].use_joystick)
1977 if (!SDLOpenJoystick(joystick_nr))
1980 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1985 joystick.status = JOYSTICK_ACTIVATED;
1989 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1991 if (nr < 0 || nr >= MAX_PLAYERS)
1995 *x = sdl_js_axis[nr][0];
1997 *y = sdl_js_axis[nr][1];
2000 *b1 = sdl_js_button[nr][0];
2002 *b2 = sdl_js_button[nr][1];
2007 #endif /* TARGET_SDL */