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);
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 unsigned int color_r = (color >> 16) & 0xff;
253 unsigned int color_g = (color >> 8) & 0xff;
254 unsigned int color_b = (color >> 0) & 0xff;
257 #ifdef FULLSCREEN_BUG
258 if (dst_bitmap == backbuffer || dst_bitmap == window)
271 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
273 SDL_FillRect(real_dst_bitmap->surface, &rect,
274 SDL_MapRGB(real_dst_bitmap->surface->format,
275 color_r, color_g, color_b));
278 if (dst_bitmap == window)
279 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
282 inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
283 int to_x, int to_y, Uint32 color)
285 SDL_Surface *surface = dst_bitmap->surface;
288 unsigned int color_r = (color >> 16) & 0xff;
289 unsigned int color_g = (color >> 8) & 0xff;
290 unsigned int color_b = (color >> 0) & 0xff;
294 swap_numbers(&from_x, &to_x);
297 swap_numbers(&from_y, &to_y);
301 rect.w = (to_x - from_x + 1);
302 rect.h = (to_y - from_y + 1);
304 #ifdef FULLSCREEN_BUG
305 if (dst_bitmap == backbuffer || dst_bitmap == window)
307 rect.x += video_xoffset;
308 rect.y += video_yoffset;
313 SDL_FillRect(surface, &rect, color);
315 SDL_FillRect(surface, &rect,
316 SDL_MapRGB(surface->format, color_r, color_g, color_b));
320 inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
321 int to_x, int to_y, Uint32 color)
323 #ifdef FULLSCREEN_BUG
324 if (dst_bitmap == backbuffer || dst_bitmap == window)
326 from_x += video_xoffset;
327 from_y += video_yoffset;
328 to_x += video_xoffset;
329 to_y += video_yoffset;
333 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
337 inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
338 int num_points, Uint32 color)
343 for (i=0; i<num_points - 1; i++)
345 for (x=0; x<line_width; x++)
347 for (y=0; y<line_width; y++)
349 int dx = x - line_width / 2;
350 int dy = y - line_width / 2;
352 if ((x == 0 && y == 0) ||
353 (x == 0 && y == line_width - 1) ||
354 (x == line_width - 1 && y == 0) ||
355 (x == line_width - 1 && y == line_width - 1))
358 sge_Line(surface, points[i].x + dx, points[i].y + dy,
359 points[i+1].x + dx, points[i+1].y + dy, color);
366 inline Pixel SDLGetPixel(Bitmap *dst_bitmap, int x, int y)
368 SDL_Surface *surface = dst_bitmap->surface;
370 #ifdef FULLSCREEN_BUG
371 if (dst_bitmap == backbuffer || dst_bitmap == window)
378 switch (surface->format->BytesPerPixel)
380 case 1: /* assuming 8-bpp */
382 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
386 case 2: /* probably 15-bpp or 16-bpp */
388 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
392 case 3: /* slow 24-bpp mode; usually not used */
394 /* does this work? */
395 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
399 shift = surface->format->Rshift;
400 color |= *(pix + shift / 8) >> shift;
401 shift = surface->format->Gshift;
402 color |= *(pix + shift / 8) >> shift;
403 shift = surface->format->Bshift;
404 color |= *(pix + shift / 8) >> shift;
410 case 4: /* probably 32-bpp */
412 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
421 /* ========================================================================= */
422 /* The following functions were taken from the SGE library */
423 /* (SDL Graphics Extension Library) by Anders Lindström */
424 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
425 /* ========================================================================= */
427 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
429 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
431 switch (surface->format->BytesPerPixel)
436 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
442 /* Probably 15-bpp or 16-bpp */
443 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
449 /* Slow 24-bpp mode, usually not used */
453 /* Gack - slow, but endian correct */
454 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
455 shift = surface->format->Rshift;
456 *(pix+shift/8) = color>>shift;
457 shift = surface->format->Gshift;
458 *(pix+shift/8) = color>>shift;
459 shift = surface->format->Bshift;
460 *(pix+shift/8) = color>>shift;
466 /* Probably 32-bpp */
467 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
474 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
475 Uint8 R, Uint8 G, Uint8 B)
477 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
480 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
482 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
485 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
487 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
490 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
495 /* Gack - slow, but endian correct */
496 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
497 shift = surface->format->Rshift;
498 *(pix+shift/8) = color>>shift;
499 shift = surface->format->Gshift;
500 *(pix+shift/8) = color>>shift;
501 shift = surface->format->Bshift;
502 *(pix+shift/8) = color>>shift;
505 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
507 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
510 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
512 switch (dest->format->BytesPerPixel)
515 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
519 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
523 _PutPixel24(dest,x,y,color);
527 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
532 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
534 if (SDL_MUSTLOCK(surface))
536 if (SDL_LockSurface(surface) < 0)
542 _PutPixel(surface, x, y, color);
544 if (SDL_MUSTLOCK(surface))
546 SDL_UnlockSurface(surface);
550 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
551 Uint8 r, Uint8 g, Uint8 b)
553 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
556 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
558 if (y >= 0 && y <= dest->h - 1)
560 switch (dest->format->BytesPerPixel)
563 return y*dest->pitch;
567 return y*dest->pitch/2;
571 return y*dest->pitch;
575 return y*dest->pitch/4;
583 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
585 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
587 switch (surface->format->BytesPerPixel)
592 *((Uint8 *)surface->pixels + ypitch + x) = color;
598 /* Probably 15-bpp or 16-bpp */
599 *((Uint16 *)surface->pixels + ypitch + x) = color;
605 /* Slow 24-bpp mode, usually not used */
609 /* Gack - slow, but endian correct */
610 pix = (Uint8 *)surface->pixels + ypitch + x*3;
611 shift = surface->format->Rshift;
612 *(pix+shift/8) = color>>shift;
613 shift = surface->format->Gshift;
614 *(pix+shift/8) = color>>shift;
615 shift = surface->format->Bshift;
616 *(pix+shift/8) = color>>shift;
622 /* Probably 32-bpp */
623 *((Uint32 *)surface->pixels + ypitch + x) = color;
630 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
635 if (SDL_MUSTLOCK(Surface))
637 if (SDL_LockSurface(Surface) < 0)
650 /* Do the clipping */
651 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
655 if (x2 > Surface->w - 1)
663 SDL_FillRect(Surface, &l, Color);
665 if (SDL_MUSTLOCK(Surface))
667 SDL_UnlockSurface(Surface);
671 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
672 Uint8 R, Uint8 G, Uint8 B)
674 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
677 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
688 /* Do the clipping */
689 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
693 if (x2 > Surface->w - 1)
701 SDL_FillRect(Surface, &l, Color);
704 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
709 if (SDL_MUSTLOCK(Surface))
711 if (SDL_LockSurface(Surface) < 0)
724 /* Do the clipping */
725 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
729 if (y2 > Surface->h - 1)
737 SDL_FillRect(Surface, &l, Color);
739 if (SDL_MUSTLOCK(Surface))
741 SDL_UnlockSurface(Surface);
745 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
746 Uint8 R, Uint8 G, Uint8 B)
748 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
751 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
762 /* Do the clipping */
763 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
767 if (y2 > Surface->h - 1)
775 SDL_FillRect(Surface, &l, Color);
778 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
779 Sint16 x2, Sint16 y2, Uint32 Color,
780 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
783 Sint16 dx, dy, sdx, sdy, x, y, px, py;
788 sdx = (dx < 0) ? -1 : 1;
789 sdy = (dy < 0) ? -1 : 1;
801 for (x = 0; x < dx; x++)
803 Callback(Surface, px, py, Color);
817 for (y = 0; y < dy; y++)
819 Callback(Surface, px, py, Color);
833 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
834 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
835 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
838 sge_DoLine(Surface, X1, Y1, X2, Y2,
839 SDL_MapRGB(Surface->format, R, G, B), Callback);
842 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
845 if (SDL_MUSTLOCK(Surface))
847 if (SDL_LockSurface(Surface) < 0)
852 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
854 /* unlock the display */
855 if (SDL_MUSTLOCK(Surface))
857 SDL_UnlockSurface(Surface);
861 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
862 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
864 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
869 -----------------------------------------------------------------------------
870 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
871 -----------------------------------------------------------------------------
874 inline void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
875 int width, int height, Uint32 color)
877 SDL_Surface *surface = bitmap->surface;
880 for (y=src_y; y < src_y + height; y++)
882 for (x=src_x; x < src_x + width; x++)
884 Uint32 pixel = SDLGetPixel(bitmap, x, y);
886 sge_PutPixel(surface, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
892 /* ========================================================================= */
893 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
894 /* (Rotozoomer) by Andreas Schiffler */
895 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
896 /* ========================================================================= */
899 -----------------------------------------------------------------------------
902 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
903 -----------------------------------------------------------------------------
914 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
916 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
917 tColorRGBA *sp, *csp, *dp;
921 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
922 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
924 /* allocate memory for row increments */
925 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
926 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
928 /* precalculate row increments */
931 for (x = 0; x <= dst->w; x++)
941 for (y = 0; y <= dst->h; y++)
950 sp = csp = (tColorRGBA *) src->pixels;
951 dp = (tColorRGBA *) dst->pixels;
952 sgap = src->pitch - src->w * 4;
953 dgap = dst->pitch - dst->w * 4;
956 for (y = 0; y < dst->h; y++)
961 for (x = 0; x < dst->w; x++)
966 /* advance source pointers */
970 /* advance destination pointer */
974 /* advance source pointer */
976 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
978 /* advance destination pointers */
979 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
989 -----------------------------------------------------------------------------
992 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
993 -----------------------------------------------------------------------------
996 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
998 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
999 Uint8 *sp, *dp, *csp;
1002 /* variable setup */
1003 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1004 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1006 /* allocate memory for row increments */
1007 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1008 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1010 /* precalculate row increments */
1013 for (x = 0; x < dst->w; x++)
1016 *csax = (csx >> 16);
1023 for (y = 0; y < dst->h; y++)
1026 *csay = (csy >> 16);
1033 for (x = 0; x < dst->w; x++)
1041 for (y = 0; y < dst->h; y++)
1048 sp = csp = (Uint8 *) src->pixels;
1049 dp = (Uint8 *) dst->pixels;
1050 dgap = dst->pitch - dst->w;
1054 for (y = 0; y < dst->h; y++)
1058 for (x = 0; x < dst->w; x++)
1063 /* advance source pointers */
1067 /* advance destination pointer */
1071 /* advance source pointer (for row) */
1072 csp += ((*csay) * src->pitch);
1075 /* advance destination pointers */
1086 -----------------------------------------------------------------------------
1089 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1090 'zoomx' and 'zoomy' are scaling factors for width and height.
1091 If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
1092 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1093 into a 32bit RGBA format on the fly.
1094 -----------------------------------------------------------------------------
1097 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1099 SDL_Surface *zoom_src = NULL;
1100 SDL_Surface *zoom_dst = NULL;
1101 boolean is_converted = FALSE;
1108 /* determine if source surface is 32 bit or 8 bit */
1109 is_32bit = (src->format->BitsPerPixel == 32);
1111 if (is_32bit || src->format->BitsPerPixel == 8)
1113 /* use source surface 'as is' */
1118 /* new source surface is 32 bit with a defined RGB ordering */
1119 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1120 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1121 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1123 is_converted = TRUE;
1126 /* allocate surface to completely contain the zoomed surface */
1129 /* target surface is 32 bit with source RGBA/ABGR ordering */
1130 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1131 zoom_src->format->Rmask,
1132 zoom_src->format->Gmask,
1133 zoom_src->format->Bmask, 0);
1137 /* target surface is 8 bit */
1138 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1142 /* lock source surface */
1143 SDL_LockSurface(zoom_src);
1145 /* check which kind of surface we have */
1148 /* call the 32 bit transformation routine to do the zooming */
1149 zoomSurfaceRGBA(zoom_src, zoom_dst);
1154 for (i=0; i < zoom_src->format->palette->ncolors; i++)
1155 zoom_dst->format->palette->colors[i] =
1156 zoom_src->format->palette->colors[i];
1157 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1159 /* call the 8 bit transformation routine to do the zooming */
1160 zoomSurfaceY(zoom_src, zoom_dst);
1163 /* unlock source surface */
1164 SDL_UnlockSurface(zoom_src);
1166 /* free temporary surface */
1168 SDL_FreeSurface(zoom_src);
1170 /* return destination surface */
1174 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1176 SDL_Surface *sdl_surface_tmp;
1177 int dst_width = dst_bitmap->width;
1178 int dst_height = dst_bitmap->height;
1180 /* throw away old destination surface */
1181 SDL_FreeSurface(dst_bitmap->surface);
1183 /* create zoomed temporary surface from source surface */
1184 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1186 /* create native format destination surface from zoomed temporary surface */
1187 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1189 /* free temporary surface */
1190 SDL_FreeSurface(sdl_surface_tmp);
1194 /* ========================================================================= */
1195 /* load image to bitmap */
1196 /* ========================================================================= */
1198 Bitmap *SDLLoadImage(char *filename)
1200 Bitmap *new_bitmap = CreateBitmapStruct();
1201 SDL_Surface *sdl_image_tmp;
1203 /* load image to temporary surface */
1204 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1206 SetError("IMG_Load(): %s", SDL_GetError());
1210 /* create native non-transparent surface for current image */
1211 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1213 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1217 /* create native transparent surface for current image */
1218 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1219 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1220 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1222 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1226 /* free temporary surface */
1227 SDL_FreeSurface(sdl_image_tmp);
1229 new_bitmap->width = new_bitmap->surface->w;
1230 new_bitmap->height = new_bitmap->surface->h;
1236 /* ------------------------------------------------------------------------- */
1237 /* custom cursor fuctions */
1238 /* ------------------------------------------------------------------------- */
1240 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1242 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1243 cursor_info->width, cursor_info->height,
1244 cursor_info->hot_x, cursor_info->hot_y);
1247 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1249 static struct MouseCursorInfo *last_cursor_info = NULL;
1250 static SDL_Cursor *cursor_default = NULL;
1251 static SDL_Cursor *cursor_current = NULL;
1253 if (cursor_default == NULL)
1254 cursor_default = SDL_GetCursor();
1256 if (cursor_info != NULL && cursor_info != last_cursor_info)
1258 cursor_current = create_cursor(cursor_info);
1259 last_cursor_info = cursor_info;
1262 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1266 /* ========================================================================= */
1267 /* audio functions */
1268 /* ========================================================================= */
1270 inline void SDLOpenAudio(void)
1272 if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
1273 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1275 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1277 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1281 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1282 AUDIO_NUM_CHANNELS_STEREO,
1283 setup.system.audio_fragment_size) < 0)
1285 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1289 audio.sound_available = TRUE;
1290 audio.music_available = TRUE;
1291 audio.loops_available = TRUE;
1292 audio.sound_enabled = TRUE;
1294 /* set number of available mixer channels */
1295 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1296 audio.music_channel = MUSIC_CHANNEL;
1297 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1299 Mixer_InitChannels();
1302 inline void SDLCloseAudio(void)
1305 Mix_HaltChannel(-1);
1308 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1312 /* ========================================================================= */
1313 /* event functions */
1314 /* ========================================================================= */
1316 inline void SDLNextEvent(Event *event)
1318 SDL_WaitEvent(event);
1320 #ifdef FULLSCREEN_BUG
1321 if (event->type == EVENT_BUTTONPRESS ||
1322 event->type == EVENT_BUTTONRELEASE)
1324 if (((ButtonEvent *)event)->x > video_xoffset)
1325 ((ButtonEvent *)event)->x -= video_xoffset;
1327 ((ButtonEvent *)event)->x = 0;
1328 if (((ButtonEvent *)event)->y > video_yoffset)
1329 ((ButtonEvent *)event)->y -= video_yoffset;
1331 ((ButtonEvent *)event)->y = 0;
1333 else if (event->type == EVENT_MOTIONNOTIFY)
1335 if (((ButtonEvent *)event)->x > video_xoffset)
1336 ((ButtonEvent *)event)->x -= video_xoffset;
1338 ((ButtonEvent *)event)->x = 0;
1339 if (((ButtonEvent *)event)->y > video_yoffset)
1340 ((ButtonEvent *)event)->y -= video_yoffset;
1342 ((ButtonEvent *)event)->y = 0;
1348 /* ========================================================================= */
1349 /* joystick functions */
1350 /* ========================================================================= */
1352 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1353 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1354 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1356 static boolean SDLOpenJoystick(int nr)
1358 if (nr < 0 || nr > MAX_PLAYERS)
1361 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1364 static void SDLCloseJoystick(int nr)
1366 if (nr < 0 || nr > MAX_PLAYERS)
1369 SDL_JoystickClose(sdl_joystick[nr]);
1372 static boolean SDLCheckJoystickOpened(int nr)
1374 if (nr < 0 || nr > MAX_PLAYERS)
1377 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1380 void HandleJoystickEvent(Event *event)
1384 case SDL_JOYAXISMOTION:
1385 if (event->jaxis.axis < 2)
1386 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1389 case SDL_JOYBUTTONDOWN:
1390 if (event->jbutton.button < 2)
1391 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1394 case SDL_JOYBUTTONUP:
1395 if (event->jbutton.button < 2)
1396 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1404 void SDLInitJoysticks()
1406 static boolean sdl_joystick_subsystem_initialized = FALSE;
1409 if (!sdl_joystick_subsystem_initialized)
1411 sdl_joystick_subsystem_initialized = TRUE;
1413 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1415 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1420 for (i=0; i<MAX_PLAYERS; i++)
1422 char *device_name = setup.input[i].joy.device_name;
1423 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1425 if (joystick_nr >= SDL_NumJoysticks())
1428 /* misuse joystick file descriptor variable to store joystick number */
1429 joystick.fd[i] = joystick_nr;
1431 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1432 if (SDLCheckJoystickOpened(joystick_nr))
1433 SDLCloseJoystick(joystick_nr);
1435 if (!setup.input[i].use_joystick)
1438 if (!SDLOpenJoystick(joystick_nr))
1440 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1444 joystick.status = JOYSTICK_ACTIVATED;
1448 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1450 if (nr < 0 || nr >= MAX_PLAYERS)
1454 *x = sdl_js_axis[nr][0];
1456 *y = sdl_js_axis[nr][1];
1459 *b1 = sdl_js_button[nr][0];
1461 *b2 = sdl_js_button[nr][1];
1466 #endif /* TARGET_SDL */