1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2002 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 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
29 /* #ifdef PLATFORM_WIN32 */
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 void SDLInitVideoDisplay(void)
43 putenv("SDL_VIDEO_CENTERED=1");
45 /* initialize SDL video */
46 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
47 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
49 /* set default SDL depth */
50 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
53 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
58 static int screen_xy[][2] =
67 /* default: normal game window size */
68 fullscreen_width = video.width;
69 fullscreen_height = video.height;
70 fullscreen_xoffset = 0;
71 fullscreen_yoffset = 0;
74 for (i = 0; screen_xy[i][0] != -1; i++)
76 if (video.width <= screen_xy[i][0] && video.height <= screen_xy[i][1])
78 fullscreen_width = screen_xy[i][0];
79 fullscreen_height = screen_xy[i][1];
84 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
85 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
88 /* open SDL video output device (window or fullscreen mode) */
89 if (!SDLSetVideoMode(backbuffer, fullscreen))
90 Error(ERR_EXIT, "setting video mode failed");
92 /* set window and icon title */
93 SDL_WM_SetCaption(program.window_title, program.window_title);
95 /* SDL cannot directly draw to the visible video framebuffer like X11,
96 but always uses a backbuffer, which is then blitted to the visible
97 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
98 visible video framebuffer with 'SDL_Flip', if the hardware supports
99 this). Therefore do not use an additional backbuffer for drawing, but
100 use a symbolic buffer (distinguishable from the SDL backbuffer) called
101 'window', which indicates that the SDL backbuffer should be updated to
102 the visible video framebuffer when attempting to blit to it.
104 For convenience, it seems to be a good idea to create this symbolic
105 buffer 'window' at the same size as the SDL backbuffer. Although it
106 should never be drawn to directly, it would do no harm nevertheless. */
108 /* create additional (symbolic) buffer for double-buffering */
109 *window = CreateBitmap(video.width, video.height, video.depth);
112 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
114 boolean success = TRUE;
115 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
116 int surface_flags_window = SURFACE_FLAGS;
117 SDL_Surface *new_surface = NULL;
119 if (*backbuffer == NULL)
120 *backbuffer = CreateBitmapStruct();
122 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
124 video_xoffset = fullscreen_xoffset;
125 video_yoffset = fullscreen_yoffset;
127 /* switch display to fullscreen mode, if available */
128 if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
129 video.depth, surface_flags_fullscreen))
132 /* switching display to fullscreen mode failed */
133 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
135 /* do not try it again */
136 video.fullscreen_available = FALSE;
141 (*backbuffer)->surface = new_surface;
143 video.fullscreen_enabled = TRUE;
148 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
153 /* switch display to window mode */
154 if ((new_surface = SDL_SetVideoMode(video.width, video.height,
155 video.depth, surface_flags_window))
158 /* switching display to window mode failed -- should not happen */
159 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
165 (*backbuffer)->surface = new_surface;
167 video.fullscreen_enabled = FALSE;
175 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
178 SDL_Surface *surface_tmp, *surface_native;
180 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
183 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
185 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
186 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
188 SDL_FreeSurface(surface_tmp);
190 new_bitmap->surface = surface_native;
193 void SDLFreeBitmapPointers(Bitmap *bitmap)
196 SDL_FreeSurface(bitmap->surface);
197 if (bitmap->surface_masked)
198 SDL_FreeSurface(bitmap->surface_masked);
199 bitmap->surface = NULL;
200 bitmap->surface_masked = NULL;
203 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
204 int src_x, int src_y, int width, int height,
205 int dst_x, int dst_y, int mask_mode)
207 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
208 SDL_Rect src_rect, dst_rect;
210 #ifdef FULLSCREEN_BUG
211 if (src_bitmap == backbuffer)
213 src_x += video_xoffset;
214 src_y += video_yoffset;
223 #ifdef FULLSCREEN_BUG
224 if (dst_bitmap == backbuffer || dst_bitmap == window)
226 dst_x += video_xoffset;
227 dst_y += video_yoffset;
236 if (src_bitmap != backbuffer || dst_bitmap != window)
237 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
238 src_bitmap->surface_masked : src_bitmap->surface),
239 &src_rect, real_dst_bitmap->surface, &dst_rect);
241 if (dst_bitmap == window)
242 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
245 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
246 int width, int height, Uint32 color)
248 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
251 #ifdef FULLSCREEN_BUG
252 if (dst_bitmap == backbuffer || dst_bitmap == window)
264 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
266 if (dst_bitmap == window)
267 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
270 void SDLFadeScreen(Bitmap *bitmap_cross, int fade_mode, int fade_delay,
273 static boolean initialization_needed = TRUE;
274 static SDL_Surface *surface_screen_copy = NULL;
275 static SDL_Surface *surface_black = NULL;
276 SDL_Surface *surface_screen = backbuffer->surface;
277 SDL_Surface *surface_cross; /* initialized later */
278 boolean fade_reverse; /* initialized later */
279 unsigned int time_last, time_current;
283 if (initialization_needed)
285 unsigned int flags = SDL_SRCALPHA;
287 /* use same surface type as screen surface */
288 if ((surface_screen->flags & SDL_HWSURFACE))
289 flags |= SDL_HWSURFACE;
291 flags |= SDL_SWSURFACE;
293 /* create surface for temporary copy of screen buffer */
294 if ((surface_screen_copy =
295 SDL_CreateRGBSurface(flags,
298 surface_screen->format->BitsPerPixel,
299 surface_screen->format->Rmask,
300 surface_screen->format->Gmask,
301 surface_screen->format->Bmask,
302 surface_screen->format->Amask)) == NULL)
303 Error(ERR_EXIT, "SDL_CreateRGBSurface( ) failed: %s", SDL_GetError());
305 /* create black surface for fading from/to black */
307 SDL_CreateRGBSurface(flags,
310 surface_screen->format->BitsPerPixel,
311 surface_screen->format->Rmask,
312 surface_screen->format->Gmask,
313 surface_screen->format->Bmask,
314 surface_screen->format->Amask)) == NULL)
315 Error(ERR_EXIT, "SDL_CreateRGBSurface( ) failed: %s", SDL_GetError());
317 /* completely fill the surface with black color pixels */
318 SDL_FillRect(surface_black, NULL,
319 SDL_MapRGB(surface_screen->format, 0, 0, 0));
321 initialization_needed = FALSE;
324 /* copy the current screen backbuffer to the temporary screen copy buffer */
325 SDL_BlitSurface(surface_screen, NULL, surface_screen_copy, NULL);
327 fade_reverse = (fade_mode == FADE_MODE_FADE_IN ? TRUE : FALSE);
328 surface_cross = (fade_mode == FADE_MODE_CROSSFADE ? bitmap_cross->surface :
331 time_current = SDL_GetTicks();
333 for (alpha = 0.0; alpha < 255.0;)
335 time_last = time_current;
336 time_current = SDL_GetTicks();
337 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
338 alpha_final = (int)(fade_reverse ? 255.0 - alpha : alpha);
339 alpha_final = MIN(MAX(0, alpha_final), 255);
341 /* draw existing image to screen buffer */
342 SDL_BlitSurface(surface_screen_copy, NULL, surface_screen, NULL);
344 /* draw new image to screen buffer using alpha blending */
345 SDL_SetAlpha(surface_cross, SDL_SRCALPHA, alpha_final);
346 SDL_BlitSurface(surface_cross, NULL, surface_screen, NULL);
348 /* draw screen buffer to visible display */
349 SDL_Flip(surface_screen);
355 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
356 int to_x, int to_y, Uint32 color)
358 SDL_Surface *surface = dst_bitmap->surface;
362 swap_numbers(&from_x, &to_x);
365 swap_numbers(&from_y, &to_y);
369 rect.w = (to_x - from_x + 1);
370 rect.h = (to_y - from_y + 1);
372 #ifdef FULLSCREEN_BUG
373 if (dst_bitmap == backbuffer || dst_bitmap == window)
375 rect.x += video_xoffset;
376 rect.y += video_yoffset;
380 SDL_FillRect(surface, &rect, color);
383 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
384 int to_x, int to_y, Uint32 color)
386 #ifdef FULLSCREEN_BUG
387 if (dst_bitmap == backbuffer || dst_bitmap == window)
389 from_x += video_xoffset;
390 from_y += video_yoffset;
391 to_x += video_xoffset;
392 to_y += video_yoffset;
396 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
400 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
401 int num_points, Uint32 color)
406 for (i = 0; i < num_points - 1; i++)
408 for (x = 0; x < line_width; x++)
410 for (y = 0; y < line_width; y++)
412 int dx = x - line_width / 2;
413 int dy = y - line_width / 2;
415 if ((x == 0 && y == 0) ||
416 (x == 0 && y == line_width - 1) ||
417 (x == line_width - 1 && y == 0) ||
418 (x == line_width - 1 && y == line_width - 1))
421 sge_Line(surface, points[i].x + dx, points[i].y + dy,
422 points[i+1].x + dx, points[i+1].y + dy, color);
429 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
431 SDL_Surface *surface = src_bitmap->surface;
433 #ifdef FULLSCREEN_BUG
434 if (src_bitmap == backbuffer || src_bitmap == window)
441 switch (surface->format->BytesPerPixel)
443 case 1: /* assuming 8-bpp */
445 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
449 case 2: /* probably 15-bpp or 16-bpp */
451 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
455 case 3: /* slow 24-bpp mode; usually not used */
457 /* does this work? */
458 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
462 shift = surface->format->Rshift;
463 color |= *(pix + shift / 8) >> shift;
464 shift = surface->format->Gshift;
465 color |= *(pix + shift / 8) >> shift;
466 shift = surface->format->Bshift;
467 color |= *(pix + shift / 8) >> shift;
473 case 4: /* probably 32-bpp */
475 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
484 /* ========================================================================= */
485 /* The following functions were taken from the SGE library */
486 /* (SDL Graphics Extension Library) by Anders Lindström */
487 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
488 /* ========================================================================= */
490 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
492 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
494 switch (surface->format->BytesPerPixel)
499 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
505 /* Probably 15-bpp or 16-bpp */
506 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
512 /* Slow 24-bpp mode, usually not used */
516 /* Gack - slow, but endian correct */
517 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
518 shift = surface->format->Rshift;
519 *(pix+shift/8) = color>>shift;
520 shift = surface->format->Gshift;
521 *(pix+shift/8) = color>>shift;
522 shift = surface->format->Bshift;
523 *(pix+shift/8) = color>>shift;
529 /* Probably 32-bpp */
530 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
537 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
538 Uint8 R, Uint8 G, Uint8 B)
540 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
543 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
545 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
548 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
550 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
553 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
558 /* Gack - slow, but endian correct */
559 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
560 shift = surface->format->Rshift;
561 *(pix+shift/8) = color>>shift;
562 shift = surface->format->Gshift;
563 *(pix+shift/8) = color>>shift;
564 shift = surface->format->Bshift;
565 *(pix+shift/8) = color>>shift;
568 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
570 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
573 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
575 switch (dest->format->BytesPerPixel)
578 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
582 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
586 _PutPixel24(dest,x,y,color);
590 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
595 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
597 if (SDL_MUSTLOCK(surface))
599 if (SDL_LockSurface(surface) < 0)
605 _PutPixel(surface, x, y, color);
607 if (SDL_MUSTLOCK(surface))
609 SDL_UnlockSurface(surface);
613 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
614 Uint8 r, Uint8 g, Uint8 b)
616 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
619 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
621 if (y >= 0 && y <= dest->h - 1)
623 switch (dest->format->BytesPerPixel)
626 return y*dest->pitch;
630 return y*dest->pitch/2;
634 return y*dest->pitch;
638 return y*dest->pitch/4;
646 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
648 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
650 switch (surface->format->BytesPerPixel)
655 *((Uint8 *)surface->pixels + ypitch + x) = color;
661 /* Probably 15-bpp or 16-bpp */
662 *((Uint16 *)surface->pixels + ypitch + x) = color;
668 /* Slow 24-bpp mode, usually not used */
672 /* Gack - slow, but endian correct */
673 pix = (Uint8 *)surface->pixels + ypitch + x*3;
674 shift = surface->format->Rshift;
675 *(pix+shift/8) = color>>shift;
676 shift = surface->format->Gshift;
677 *(pix+shift/8) = color>>shift;
678 shift = surface->format->Bshift;
679 *(pix+shift/8) = color>>shift;
685 /* Probably 32-bpp */
686 *((Uint32 *)surface->pixels + ypitch + x) = color;
693 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
698 if (SDL_MUSTLOCK(Surface))
700 if (SDL_LockSurface(Surface) < 0)
713 /* Do the clipping */
714 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
718 if (x2 > Surface->w - 1)
726 SDL_FillRect(Surface, &l, Color);
728 if (SDL_MUSTLOCK(Surface))
730 SDL_UnlockSurface(Surface);
734 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
735 Uint8 R, Uint8 G, Uint8 B)
737 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
740 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
751 /* Do the clipping */
752 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
756 if (x2 > Surface->w - 1)
764 SDL_FillRect(Surface, &l, Color);
767 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
772 if (SDL_MUSTLOCK(Surface))
774 if (SDL_LockSurface(Surface) < 0)
787 /* Do the clipping */
788 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
792 if (y2 > Surface->h - 1)
800 SDL_FillRect(Surface, &l, Color);
802 if (SDL_MUSTLOCK(Surface))
804 SDL_UnlockSurface(Surface);
808 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
809 Uint8 R, Uint8 G, Uint8 B)
811 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
814 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
825 /* Do the clipping */
826 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
830 if (y2 > Surface->h - 1)
838 SDL_FillRect(Surface, &l, Color);
841 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
842 Sint16 x2, Sint16 y2, Uint32 Color,
843 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
846 Sint16 dx, dy, sdx, sdy, x, y, px, py;
851 sdx = (dx < 0) ? -1 : 1;
852 sdy = (dy < 0) ? -1 : 1;
864 for (x = 0; x < dx; x++)
866 Callback(Surface, px, py, Color);
880 for (y = 0; y < dy; y++)
882 Callback(Surface, px, py, Color);
896 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
897 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
898 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
901 sge_DoLine(Surface, X1, Y1, X2, Y2,
902 SDL_MapRGB(Surface->format, R, G, B), Callback);
905 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
908 if (SDL_MUSTLOCK(Surface))
910 if (SDL_LockSurface(Surface) < 0)
915 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
917 /* unlock the display */
918 if (SDL_MUSTLOCK(Surface))
920 SDL_UnlockSurface(Surface);
924 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
925 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
927 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
930 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
932 #ifdef FULLSCREEN_BUG
933 if (dst_bitmap == backbuffer || dst_bitmap == window)
940 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
945 -----------------------------------------------------------------------------
946 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
947 -----------------------------------------------------------------------------
950 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
951 int width, int height, Uint32 color)
955 for (y = src_y; y < src_y + height; y++)
957 for (x = src_x; x < src_x + width; x++)
959 Uint32 pixel = SDLGetPixel(bitmap, x, y);
961 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
966 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
967 int src_x, int src_y, int width, int height,
968 int dst_x, int dst_y)
972 for (y = 0; y < height; y++)
974 for (x = 0; x < width; x++)
976 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
978 if (pixel != BLACK_PIXEL)
979 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
985 /* ========================================================================= */
986 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
987 /* (Rotozoomer) by Andreas Schiffler */
988 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
989 /* ========================================================================= */
992 -----------------------------------------------------------------------------
995 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
996 -----------------------------------------------------------------------------
1007 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1009 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1010 tColorRGBA *sp, *csp, *dp;
1013 /* variable setup */
1014 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1015 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1017 /* allocate memory for row increments */
1018 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1019 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1021 /* precalculate row increments */
1024 for (x = 0; x <= dst->w; x++)
1034 for (y = 0; y <= dst->h; y++)
1043 sp = csp = (tColorRGBA *) src->pixels;
1044 dp = (tColorRGBA *) dst->pixels;
1045 sgap = src->pitch - src->w * 4;
1046 dgap = dst->pitch - dst->w * 4;
1049 for (y = 0; y < dst->h; y++)
1054 for (x = 0; x < dst->w; x++)
1059 /* advance source pointers */
1061 sp += (*csax >> 16);
1063 /* advance destination pointer */
1067 /* advance source pointer */
1069 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1071 /* advance destination pointers */
1072 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1082 -----------------------------------------------------------------------------
1085 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1086 -----------------------------------------------------------------------------
1089 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1091 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1092 Uint8 *sp, *dp, *csp;
1095 /* variable setup */
1096 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1097 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1099 /* allocate memory for row increments */
1100 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1101 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1103 /* precalculate row increments */
1106 for (x = 0; x < dst->w; x++)
1109 *csax = (csx >> 16);
1116 for (y = 0; y < dst->h; y++)
1119 *csay = (csy >> 16);
1126 for (x = 0; x < dst->w; x++)
1134 for (y = 0; y < dst->h; y++)
1141 sp = csp = (Uint8 *) src->pixels;
1142 dp = (Uint8 *) dst->pixels;
1143 dgap = dst->pitch - dst->w;
1147 for (y = 0; y < dst->h; y++)
1151 for (x = 0; x < dst->w; x++)
1156 /* advance source pointers */
1160 /* advance destination pointer */
1164 /* advance source pointer (for row) */
1165 csp += ((*csay) * src->pitch);
1168 /* advance destination pointers */
1179 -----------------------------------------------------------------------------
1182 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1183 'zoomx' and 'zoomy' are scaling factors for width and height.
1184 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1185 into a 32bit RGBA format on the fly.
1186 -----------------------------------------------------------------------------
1189 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1191 SDL_Surface *zoom_src = NULL;
1192 SDL_Surface *zoom_dst = NULL;
1193 boolean is_converted = FALSE;
1200 /* determine if source surface is 32 bit or 8 bit */
1201 is_32bit = (src->format->BitsPerPixel == 32);
1203 if (is_32bit || src->format->BitsPerPixel == 8)
1205 /* use source surface 'as is' */
1210 /* new source surface is 32 bit with a defined RGB ordering */
1211 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1212 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1213 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1215 is_converted = TRUE;
1218 /* allocate surface to completely contain the zoomed surface */
1221 /* target surface is 32 bit with source RGBA/ABGR ordering */
1222 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1223 zoom_src->format->Rmask,
1224 zoom_src->format->Gmask,
1225 zoom_src->format->Bmask, 0);
1229 /* target surface is 8 bit */
1230 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1234 /* lock source surface */
1235 SDL_LockSurface(zoom_src);
1237 /* check which kind of surface we have */
1240 /* call the 32 bit transformation routine to do the zooming */
1241 zoomSurfaceRGBA(zoom_src, zoom_dst);
1246 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1247 zoom_dst->format->palette->colors[i] =
1248 zoom_src->format->palette->colors[i];
1249 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1251 /* call the 8 bit transformation routine to do the zooming */
1252 zoomSurfaceY(zoom_src, zoom_dst);
1255 /* unlock source surface */
1256 SDL_UnlockSurface(zoom_src);
1258 /* free temporary surface */
1260 SDL_FreeSurface(zoom_src);
1262 /* return destination surface */
1266 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1268 SDL_Surface *sdl_surface_tmp;
1269 int dst_width = dst_bitmap->width;
1270 int dst_height = dst_bitmap->height;
1272 /* throw away old destination surface */
1273 SDL_FreeSurface(dst_bitmap->surface);
1275 /* create zoomed temporary surface from source surface */
1276 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1278 /* create native format destination surface from zoomed temporary surface */
1279 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1281 /* free temporary surface */
1282 SDL_FreeSurface(sdl_surface_tmp);
1286 /* ========================================================================= */
1287 /* load image to bitmap */
1288 /* ========================================================================= */
1290 Bitmap *SDLLoadImage(char *filename)
1292 Bitmap *new_bitmap = CreateBitmapStruct();
1293 SDL_Surface *sdl_image_tmp;
1295 /* load image to temporary surface */
1296 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1298 SetError("IMG_Load(): %s", SDL_GetError());
1302 /* create native non-transparent surface for current image */
1303 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1305 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1309 /* create native transparent surface for current image */
1310 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1311 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1312 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1314 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1318 /* free temporary surface */
1319 SDL_FreeSurface(sdl_image_tmp);
1321 new_bitmap->width = new_bitmap->surface->w;
1322 new_bitmap->height = new_bitmap->surface->h;
1328 /* ------------------------------------------------------------------------- */
1329 /* custom cursor fuctions */
1330 /* ------------------------------------------------------------------------- */
1332 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1334 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1335 cursor_info->width, cursor_info->height,
1336 cursor_info->hot_x, cursor_info->hot_y);
1339 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1341 static struct MouseCursorInfo *last_cursor_info = NULL;
1342 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1343 static SDL_Cursor *cursor_default = NULL;
1344 static SDL_Cursor *cursor_current = NULL;
1346 /* if invoked for the first time, store the SDL default cursor */
1347 if (cursor_default == NULL)
1348 cursor_default = SDL_GetCursor();
1350 /* only create new cursor if cursor info (custom only) has changed */
1351 if (cursor_info != NULL && cursor_info != last_cursor_info)
1353 cursor_current = create_cursor(cursor_info);
1354 last_cursor_info = cursor_info;
1357 /* only set new cursor if cursor info (custom or NULL) has changed */
1358 if (cursor_info != last_cursor_info2)
1359 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1361 last_cursor_info2 = cursor_info;
1365 /* ========================================================================= */
1366 /* audio functions */
1367 /* ========================================================================= */
1369 void SDLOpenAudio(void)
1371 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
1372 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1374 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1376 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1380 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1381 AUDIO_NUM_CHANNELS_STEREO,
1382 setup.system.audio_fragment_size) < 0)
1384 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1388 audio.sound_available = TRUE;
1389 audio.music_available = TRUE;
1390 audio.loops_available = TRUE;
1391 audio.sound_enabled = TRUE;
1393 /* set number of available mixer channels */
1394 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1395 audio.music_channel = MUSIC_CHANNEL;
1396 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1398 Mixer_InitChannels();
1401 void SDLCloseAudio(void)
1404 Mix_HaltChannel(-1);
1407 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1411 /* ========================================================================= */
1412 /* event functions */
1413 /* ========================================================================= */
1415 void SDLNextEvent(Event *event)
1417 SDL_WaitEvent(event);
1419 #ifdef FULLSCREEN_BUG
1420 if (event->type == EVENT_BUTTONPRESS ||
1421 event->type == EVENT_BUTTONRELEASE)
1423 if (((ButtonEvent *)event)->x > video_xoffset)
1424 ((ButtonEvent *)event)->x -= video_xoffset;
1426 ((ButtonEvent *)event)->x = 0;
1427 if (((ButtonEvent *)event)->y > video_yoffset)
1428 ((ButtonEvent *)event)->y -= video_yoffset;
1430 ((ButtonEvent *)event)->y = 0;
1432 else if (event->type == EVENT_MOTIONNOTIFY)
1434 if (((MotionEvent *)event)->x > video_xoffset)
1435 ((MotionEvent *)event)->x -= video_xoffset;
1437 ((MotionEvent *)event)->x = 0;
1438 if (((MotionEvent *)event)->y > video_yoffset)
1439 ((MotionEvent *)event)->y -= video_yoffset;
1441 ((MotionEvent *)event)->y = 0;
1447 /* ========================================================================= */
1448 /* joystick functions */
1449 /* ========================================================================= */
1451 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1452 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1453 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1455 static boolean SDLOpenJoystick(int nr)
1457 if (nr < 0 || nr > MAX_PLAYERS)
1460 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1463 static void SDLCloseJoystick(int nr)
1465 if (nr < 0 || nr > MAX_PLAYERS)
1468 SDL_JoystickClose(sdl_joystick[nr]);
1471 static boolean SDLCheckJoystickOpened(int nr)
1473 if (nr < 0 || nr > MAX_PLAYERS)
1476 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1479 void HandleJoystickEvent(Event *event)
1483 case SDL_JOYAXISMOTION:
1484 if (event->jaxis.axis < 2)
1485 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1488 case SDL_JOYBUTTONDOWN:
1489 if (event->jbutton.button < 2)
1490 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1493 case SDL_JOYBUTTONUP:
1494 if (event->jbutton.button < 2)
1495 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1503 void SDLInitJoysticks()
1505 static boolean sdl_joystick_subsystem_initialized = FALSE;
1506 boolean print_warning = !sdl_joystick_subsystem_initialized;
1509 if (!sdl_joystick_subsystem_initialized)
1511 sdl_joystick_subsystem_initialized = TRUE;
1513 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1515 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1520 for (i = 0; i < MAX_PLAYERS; i++)
1522 /* get configured joystick for this player */
1523 char *device_name = setup.input[i].joy.device_name;
1524 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1526 if (joystick_nr >= SDL_NumJoysticks())
1528 if (setup.input[i].use_joystick && print_warning)
1529 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
1534 /* misuse joystick file descriptor variable to store joystick number */
1535 joystick.fd[i] = joystick_nr;
1537 if (joystick_nr == -1)
1540 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1541 if (SDLCheckJoystickOpened(joystick_nr))
1542 SDLCloseJoystick(joystick_nr);
1544 if (!setup.input[i].use_joystick)
1547 if (!SDLOpenJoystick(joystick_nr))
1550 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1555 joystick.status = JOYSTICK_ACTIVATED;
1559 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1561 if (nr < 0 || nr >= MAX_PLAYERS)
1565 *x = sdl_js_axis[nr][0];
1567 *y = sdl_js_axis[nr][1];
1570 *b1 = sdl_js_button[nr][0];
1572 *b2 = sdl_js_button[nr][1];
1577 #endif /* TARGET_SDL */