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 inline 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 inline 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 inline 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 inline 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 inline void SDLCreateBitmapContent(Bitmap *new_bitmap,
176 int width, int height, int depth)
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 inline 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 inline void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
204 int src_x, int src_y,
205 int width, int height,
206 int dst_x, int dst_y, int mask_mode)
208 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
209 SDL_Rect src_rect, dst_rect;
211 #ifdef FULLSCREEN_BUG
212 if (src_bitmap == backbuffer)
214 src_x += video_xoffset;
215 src_y += video_yoffset;
224 #ifdef FULLSCREEN_BUG
225 if (dst_bitmap == backbuffer || dst_bitmap == window)
227 dst_x += video_xoffset;
228 dst_y += video_yoffset;
237 if (src_bitmap != backbuffer || dst_bitmap != window)
238 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
239 src_bitmap->surface_masked : src_bitmap->surface),
240 &src_rect, real_dst_bitmap->surface, &dst_rect);
242 if (dst_bitmap == window)
243 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
246 inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
247 int width, int height, Uint32 color)
249 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
252 #ifdef FULLSCREEN_BUG
253 if (dst_bitmap == backbuffer || dst_bitmap == window)
265 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
267 if (dst_bitmap == window)
268 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
271 inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
272 int to_x, int to_y, Uint32 color)
274 SDL_Surface *surface = dst_bitmap->surface;
278 swap_numbers(&from_x, &to_x);
281 swap_numbers(&from_y, &to_y);
285 rect.w = (to_x - from_x + 1);
286 rect.h = (to_y - from_y + 1);
288 #ifdef FULLSCREEN_BUG
289 if (dst_bitmap == backbuffer || dst_bitmap == window)
291 rect.x += video_xoffset;
292 rect.y += video_yoffset;
296 SDL_FillRect(surface, &rect, color);
299 inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
300 int to_x, int to_y, Uint32 color)
302 #ifdef FULLSCREEN_BUG
303 if (dst_bitmap == backbuffer || dst_bitmap == window)
305 from_x += video_xoffset;
306 from_y += video_yoffset;
307 to_x += video_xoffset;
308 to_y += video_yoffset;
312 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
316 inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
317 int num_points, Uint32 color)
322 for (i = 0; i < num_points - 1; i++)
324 for (x = 0; x < line_width; x++)
326 for (y = 0; y < line_width; y++)
328 int dx = x - line_width / 2;
329 int dy = y - line_width / 2;
331 if ((x == 0 && y == 0) ||
332 (x == 0 && y == line_width - 1) ||
333 (x == line_width - 1 && y == 0) ||
334 (x == line_width - 1 && y == line_width - 1))
337 sge_Line(surface, points[i].x + dx, points[i].y + dy,
338 points[i+1].x + dx, points[i+1].y + dy, color);
345 inline Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
347 SDL_Surface *surface = src_bitmap->surface;
349 #ifdef FULLSCREEN_BUG
350 if (src_bitmap == backbuffer || src_bitmap == window)
357 switch (surface->format->BytesPerPixel)
359 case 1: /* assuming 8-bpp */
361 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
365 case 2: /* probably 15-bpp or 16-bpp */
367 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
371 case 3: /* slow 24-bpp mode; usually not used */
373 /* does this work? */
374 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
378 shift = surface->format->Rshift;
379 color |= *(pix + shift / 8) >> shift;
380 shift = surface->format->Gshift;
381 color |= *(pix + shift / 8) >> shift;
382 shift = surface->format->Bshift;
383 color |= *(pix + shift / 8) >> shift;
389 case 4: /* probably 32-bpp */
391 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
400 /* ========================================================================= */
401 /* The following functions were taken from the SGE library */
402 /* (SDL Graphics Extension Library) by Anders Lindström */
403 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
404 /* ========================================================================= */
406 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
408 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
410 switch (surface->format->BytesPerPixel)
415 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
421 /* Probably 15-bpp or 16-bpp */
422 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
428 /* Slow 24-bpp mode, usually not used */
432 /* Gack - slow, but endian correct */
433 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
434 shift = surface->format->Rshift;
435 *(pix+shift/8) = color>>shift;
436 shift = surface->format->Gshift;
437 *(pix+shift/8) = color>>shift;
438 shift = surface->format->Bshift;
439 *(pix+shift/8) = color>>shift;
445 /* Probably 32-bpp */
446 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
453 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
454 Uint8 R, Uint8 G, Uint8 B)
456 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
459 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
461 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
464 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
466 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
469 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
474 /* Gack - slow, but endian correct */
475 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
476 shift = surface->format->Rshift;
477 *(pix+shift/8) = color>>shift;
478 shift = surface->format->Gshift;
479 *(pix+shift/8) = color>>shift;
480 shift = surface->format->Bshift;
481 *(pix+shift/8) = color>>shift;
484 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
486 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
489 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
491 switch (dest->format->BytesPerPixel)
494 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
498 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
502 _PutPixel24(dest,x,y,color);
506 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
511 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
513 if (SDL_MUSTLOCK(surface))
515 if (SDL_LockSurface(surface) < 0)
521 _PutPixel(surface, x, y, color);
523 if (SDL_MUSTLOCK(surface))
525 SDL_UnlockSurface(surface);
529 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
530 Uint8 r, Uint8 g, Uint8 b)
532 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
535 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
537 if (y >= 0 && y <= dest->h - 1)
539 switch (dest->format->BytesPerPixel)
542 return y*dest->pitch;
546 return y*dest->pitch/2;
550 return y*dest->pitch;
554 return y*dest->pitch/4;
562 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
564 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
566 switch (surface->format->BytesPerPixel)
571 *((Uint8 *)surface->pixels + ypitch + x) = color;
577 /* Probably 15-bpp or 16-bpp */
578 *((Uint16 *)surface->pixels + ypitch + x) = color;
584 /* Slow 24-bpp mode, usually not used */
588 /* Gack - slow, but endian correct */
589 pix = (Uint8 *)surface->pixels + ypitch + x*3;
590 shift = surface->format->Rshift;
591 *(pix+shift/8) = color>>shift;
592 shift = surface->format->Gshift;
593 *(pix+shift/8) = color>>shift;
594 shift = surface->format->Bshift;
595 *(pix+shift/8) = color>>shift;
601 /* Probably 32-bpp */
602 *((Uint32 *)surface->pixels + ypitch + x) = color;
609 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
614 if (SDL_MUSTLOCK(Surface))
616 if (SDL_LockSurface(Surface) < 0)
629 /* Do the clipping */
630 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
634 if (x2 > Surface->w - 1)
642 SDL_FillRect(Surface, &l, Color);
644 if (SDL_MUSTLOCK(Surface))
646 SDL_UnlockSurface(Surface);
650 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
651 Uint8 R, Uint8 G, Uint8 B)
653 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
656 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
667 /* Do the clipping */
668 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
672 if (x2 > Surface->w - 1)
680 SDL_FillRect(Surface, &l, Color);
683 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
688 if (SDL_MUSTLOCK(Surface))
690 if (SDL_LockSurface(Surface) < 0)
703 /* Do the clipping */
704 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
708 if (y2 > Surface->h - 1)
716 SDL_FillRect(Surface, &l, Color);
718 if (SDL_MUSTLOCK(Surface))
720 SDL_UnlockSurface(Surface);
724 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
725 Uint8 R, Uint8 G, Uint8 B)
727 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
730 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
741 /* Do the clipping */
742 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
746 if (y2 > Surface->h - 1)
754 SDL_FillRect(Surface, &l, Color);
757 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
758 Sint16 x2, Sint16 y2, Uint32 Color,
759 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
762 Sint16 dx, dy, sdx, sdy, x, y, px, py;
767 sdx = (dx < 0) ? -1 : 1;
768 sdy = (dy < 0) ? -1 : 1;
780 for (x = 0; x < dx; x++)
782 Callback(Surface, px, py, Color);
796 for (y = 0; y < dy; y++)
798 Callback(Surface, px, py, Color);
812 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
813 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
814 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
817 sge_DoLine(Surface, X1, Y1, X2, Y2,
818 SDL_MapRGB(Surface->format, R, G, B), Callback);
821 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
824 if (SDL_MUSTLOCK(Surface))
826 if (SDL_LockSurface(Surface) < 0)
831 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
833 /* unlock the display */
834 if (SDL_MUSTLOCK(Surface))
836 SDL_UnlockSurface(Surface);
840 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
841 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
843 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
846 inline void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
848 #ifdef FULLSCREEN_BUG
849 if (dst_bitmap == backbuffer || dst_bitmap == window)
856 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
861 -----------------------------------------------------------------------------
862 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
863 -----------------------------------------------------------------------------
866 inline void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
867 int width, int height, Uint32 color)
871 for (y = src_y; y < src_y + height; y++)
873 for (x = src_x; x < src_x + width; x++)
875 Uint32 pixel = SDLGetPixel(bitmap, x, y);
877 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
882 inline void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
883 int src_x, int src_y, int width, int height,
884 int dst_x, int dst_y)
888 for (y = 0; y < height; y++)
890 for (x = 0; x < width; x++)
892 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
894 if (pixel != BLACK_PIXEL)
895 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
901 /* ========================================================================= */
902 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
903 /* (Rotozoomer) by Andreas Schiffler */
904 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
905 /* ========================================================================= */
908 -----------------------------------------------------------------------------
911 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
912 -----------------------------------------------------------------------------
923 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
925 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
926 tColorRGBA *sp, *csp, *dp;
930 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
931 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
933 /* allocate memory for row increments */
934 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
935 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
937 /* precalculate row increments */
940 for (x = 0; x <= dst->w; x++)
950 for (y = 0; y <= dst->h; y++)
959 sp = csp = (tColorRGBA *) src->pixels;
960 dp = (tColorRGBA *) dst->pixels;
961 sgap = src->pitch - src->w * 4;
962 dgap = dst->pitch - dst->w * 4;
965 for (y = 0; y < dst->h; y++)
970 for (x = 0; x < dst->w; x++)
975 /* advance source pointers */
979 /* advance destination pointer */
983 /* advance source pointer */
985 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
987 /* advance destination pointers */
988 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
998 -----------------------------------------------------------------------------
1001 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1002 -----------------------------------------------------------------------------
1005 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1007 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1008 Uint8 *sp, *dp, *csp;
1011 /* variable setup */
1012 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1013 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1015 /* allocate memory for row increments */
1016 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1017 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1019 /* precalculate row increments */
1022 for (x = 0; x < dst->w; x++)
1025 *csax = (csx >> 16);
1032 for (y = 0; y < dst->h; y++)
1035 *csay = (csy >> 16);
1042 for (x = 0; x < dst->w; x++)
1050 for (y = 0; y < dst->h; y++)
1057 sp = csp = (Uint8 *) src->pixels;
1058 dp = (Uint8 *) dst->pixels;
1059 dgap = dst->pitch - dst->w;
1063 for (y = 0; y < dst->h; y++)
1067 for (x = 0; x < dst->w; x++)
1072 /* advance source pointers */
1076 /* advance destination pointer */
1080 /* advance source pointer (for row) */
1081 csp += ((*csay) * src->pitch);
1084 /* advance destination pointers */
1095 -----------------------------------------------------------------------------
1098 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1099 'zoomx' and 'zoomy' are scaling factors for width and height.
1100 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1101 into a 32bit RGBA format on the fly.
1102 -----------------------------------------------------------------------------
1105 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1107 SDL_Surface *zoom_src = NULL;
1108 SDL_Surface *zoom_dst = NULL;
1109 boolean is_converted = FALSE;
1116 /* determine if source surface is 32 bit or 8 bit */
1117 is_32bit = (src->format->BitsPerPixel == 32);
1119 if (is_32bit || src->format->BitsPerPixel == 8)
1121 /* use source surface 'as is' */
1126 /* new source surface is 32 bit with a defined RGB ordering */
1127 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1128 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1129 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1131 is_converted = TRUE;
1134 /* allocate surface to completely contain the zoomed surface */
1137 /* target surface is 32 bit with source RGBA/ABGR ordering */
1138 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1139 zoom_src->format->Rmask,
1140 zoom_src->format->Gmask,
1141 zoom_src->format->Bmask, 0);
1145 /* target surface is 8 bit */
1146 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1150 /* lock source surface */
1151 SDL_LockSurface(zoom_src);
1153 /* check which kind of surface we have */
1156 /* call the 32 bit transformation routine to do the zooming */
1157 zoomSurfaceRGBA(zoom_src, zoom_dst);
1162 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1163 zoom_dst->format->palette->colors[i] =
1164 zoom_src->format->palette->colors[i];
1165 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1167 /* call the 8 bit transformation routine to do the zooming */
1168 zoomSurfaceY(zoom_src, zoom_dst);
1171 /* unlock source surface */
1172 SDL_UnlockSurface(zoom_src);
1174 /* free temporary surface */
1176 SDL_FreeSurface(zoom_src);
1178 /* return destination surface */
1182 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1184 SDL_Surface *sdl_surface_tmp;
1185 int dst_width = dst_bitmap->width;
1186 int dst_height = dst_bitmap->height;
1188 /* throw away old destination surface */
1189 SDL_FreeSurface(dst_bitmap->surface);
1191 /* create zoomed temporary surface from source surface */
1192 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1194 /* create native format destination surface from zoomed temporary surface */
1195 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1197 /* free temporary surface */
1198 SDL_FreeSurface(sdl_surface_tmp);
1202 /* ========================================================================= */
1203 /* load image to bitmap */
1204 /* ========================================================================= */
1206 Bitmap *SDLLoadImage(char *filename)
1208 Bitmap *new_bitmap = CreateBitmapStruct();
1209 SDL_Surface *sdl_image_tmp;
1211 /* load image to temporary surface */
1212 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1214 SetError("IMG_Load(): %s", SDL_GetError());
1218 /* create native non-transparent surface for current image */
1219 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1221 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1225 /* create native transparent surface for current image */
1226 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1227 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1228 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1230 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1234 /* free temporary surface */
1235 SDL_FreeSurface(sdl_image_tmp);
1237 new_bitmap->width = new_bitmap->surface->w;
1238 new_bitmap->height = new_bitmap->surface->h;
1244 /* ------------------------------------------------------------------------- */
1245 /* custom cursor fuctions */
1246 /* ------------------------------------------------------------------------- */
1248 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1250 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1251 cursor_info->width, cursor_info->height,
1252 cursor_info->hot_x, cursor_info->hot_y);
1255 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1257 static struct MouseCursorInfo *last_cursor_info = NULL;
1258 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1259 static SDL_Cursor *cursor_default = NULL;
1260 static SDL_Cursor *cursor_current = NULL;
1262 /* if invoked for the first time, store the SDL default cursor */
1263 if (cursor_default == NULL)
1264 cursor_default = SDL_GetCursor();
1266 /* only create new cursor if cursor info (custom only) has changed */
1267 if (cursor_info != NULL && cursor_info != last_cursor_info)
1269 cursor_current = create_cursor(cursor_info);
1270 last_cursor_info = cursor_info;
1273 /* only set new cursor if cursor info (custom or NULL) has changed */
1274 if (cursor_info != last_cursor_info2)
1275 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1277 last_cursor_info2 = cursor_info;
1281 /* ========================================================================= */
1282 /* audio functions */
1283 /* ========================================================================= */
1285 inline void SDLOpenAudio(void)
1287 if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
1288 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1290 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1292 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1296 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1297 AUDIO_NUM_CHANNELS_STEREO,
1298 setup.system.audio_fragment_size) < 0)
1300 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1304 audio.sound_available = TRUE;
1305 audio.music_available = TRUE;
1306 audio.loops_available = TRUE;
1307 audio.sound_enabled = TRUE;
1309 /* set number of available mixer channels */
1310 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1311 audio.music_channel = MUSIC_CHANNEL;
1312 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1314 Mixer_InitChannels();
1317 inline void SDLCloseAudio(void)
1320 Mix_HaltChannel(-1);
1323 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1327 /* ========================================================================= */
1328 /* event functions */
1329 /* ========================================================================= */
1331 inline void SDLNextEvent(Event *event)
1333 SDL_WaitEvent(event);
1335 #ifdef FULLSCREEN_BUG
1336 if (event->type == EVENT_BUTTONPRESS ||
1337 event->type == EVENT_BUTTONRELEASE)
1339 if (((ButtonEvent *)event)->x > video_xoffset)
1340 ((ButtonEvent *)event)->x -= video_xoffset;
1342 ((ButtonEvent *)event)->x = 0;
1343 if (((ButtonEvent *)event)->y > video_yoffset)
1344 ((ButtonEvent *)event)->y -= video_yoffset;
1346 ((ButtonEvent *)event)->y = 0;
1348 else if (event->type == EVENT_MOTIONNOTIFY)
1350 if (((MotionEvent *)event)->x > video_xoffset)
1351 ((MotionEvent *)event)->x -= video_xoffset;
1353 ((MotionEvent *)event)->x = 0;
1354 if (((MotionEvent *)event)->y > video_yoffset)
1355 ((MotionEvent *)event)->y -= video_yoffset;
1357 ((MotionEvent *)event)->y = 0;
1363 /* ========================================================================= */
1364 /* joystick functions */
1365 /* ========================================================================= */
1367 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1368 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1369 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1371 static boolean SDLOpenJoystick(int nr)
1373 if (nr < 0 || nr > MAX_PLAYERS)
1376 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1379 static void SDLCloseJoystick(int nr)
1381 if (nr < 0 || nr > MAX_PLAYERS)
1384 SDL_JoystickClose(sdl_joystick[nr]);
1387 static boolean SDLCheckJoystickOpened(int nr)
1389 if (nr < 0 || nr > MAX_PLAYERS)
1392 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1395 void HandleJoystickEvent(Event *event)
1399 case SDL_JOYAXISMOTION:
1400 if (event->jaxis.axis < 2)
1401 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1404 case SDL_JOYBUTTONDOWN:
1405 if (event->jbutton.button < 2)
1406 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1409 case SDL_JOYBUTTONUP:
1410 if (event->jbutton.button < 2)
1411 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1419 void SDLInitJoysticks()
1421 static boolean sdl_joystick_subsystem_initialized = FALSE;
1422 boolean print_warning = !sdl_joystick_subsystem_initialized;
1425 if (!sdl_joystick_subsystem_initialized)
1427 sdl_joystick_subsystem_initialized = TRUE;
1429 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1431 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1436 for (i = 0; i < MAX_PLAYERS; i++)
1438 char *device_name = setup.input[i].joy.device_name;
1439 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1441 if (joystick_nr >= SDL_NumJoysticks())
1443 if (setup.input[i].use_joystick && print_warning)
1444 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
1449 /* misuse joystick file descriptor variable to store joystick number */
1450 joystick.fd[i] = joystick_nr;
1452 if (joystick_nr == -1)
1455 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1456 if (SDLCheckJoystickOpened(joystick_nr))
1457 SDLCloseJoystick(joystick_nr);
1459 if (!setup.input[i].use_joystick)
1462 if (!SDLOpenJoystick(joystick_nr))
1465 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1470 joystick.status = JOYSTICK_ACTIVATED;
1474 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1476 if (nr < 0 || nr >= MAX_PLAYERS)
1480 *x = sdl_js_axis[nr][0];
1482 *y = sdl_js_axis[nr][1];
1485 *b1 = sdl_js_button[nr][0];
1487 *b2 = sdl_js_button[nr][1];
1492 #endif /* TARGET_SDL */