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 SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
176 int src_x, int src_y,
177 int width, int height,
178 int dst_x, int dst_y, int copy_mode)
180 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
181 SDL_Rect src_rect, dst_rect;
183 #ifdef FULLSCREEN_BUG
184 if (src_bitmap == backbuffer)
186 src_x += video_xoffset;
187 src_y += video_yoffset;
196 #ifdef FULLSCREEN_BUG
197 if (dst_bitmap == backbuffer || dst_bitmap == window)
199 dst_x += video_xoffset;
200 dst_y += video_yoffset;
209 if (src_bitmap != backbuffer || dst_bitmap != window)
210 SDL_BlitSurface((copy_mode == SDLCOPYAREA_MASKED ?
211 src_bitmap->surface_masked : src_bitmap->surface),
212 &src_rect, real_dst_bitmap->surface, &dst_rect);
214 if (dst_bitmap == window)
215 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
218 inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
219 int width, int height, unsigned int color)
221 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
223 unsigned int color_r = (color >> 16) && 0xff;
224 unsigned int color_g = (color >> 8) && 0xff;
225 unsigned int color_b = (color >> 0) && 0xff;
227 #ifdef FULLSCREEN_BUG
228 if (dst_bitmap == backbuffer || dst_bitmap == window)
240 SDL_FillRect(real_dst_bitmap->surface, &rect,
241 SDL_MapRGB(real_dst_bitmap->surface->format,
242 color_r, color_g, color_b));
244 if (dst_bitmap == window)
245 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
248 inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
249 int to_x, int to_y, unsigned int color)
251 SDL_Surface *surface = dst_bitmap->surface;
253 unsigned int color_r = (color >> 16) & 0xff;
254 unsigned int color_g = (color >> 8) & 0xff;
255 unsigned int color_b = (color >> 0) & 0xff;
258 swap_numbers(&from_x, &to_x);
261 swap_numbers(&from_y, &to_y);
265 rect.w = (to_x - from_x + 1);
266 rect.h = (to_y - from_y + 1);
268 #ifdef FULLSCREEN_BUG
269 if (dst_bitmap == backbuffer || dst_bitmap == window)
271 rect.x += video_xoffset;
272 rect.y += video_yoffset;
276 SDL_FillRect(surface, &rect,
277 SDL_MapRGB(surface->format, color_r, color_g, color_b));
280 inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
281 int to_x, int to_y, Uint32 color)
283 #ifdef FULLSCREEN_BUG
284 if (dst_bitmap == backbuffer || dst_bitmap == window)
286 from_x += video_xoffset;
287 from_y += video_yoffset;
288 to_x += video_xoffset;
289 to_y += video_yoffset;
293 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
297 inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
298 int num_points, Uint32 color)
303 for (i=0; i<num_points - 1; i++)
305 for (x=0; x<line_width; x++)
307 for (y=0; y<line_width; y++)
309 int dx = x - line_width / 2;
310 int dy = y - line_width / 2;
312 if ((x == 0 && y == 0) ||
313 (x == 0 && y == line_width - 1) ||
314 (x == line_width - 1 && y == 0) ||
315 (x == line_width - 1 && y == line_width - 1))
318 sge_Line(surface, points[i].x + dx, points[i].y + dy,
319 points[i+1].x + dx, points[i+1].y + dy, color);
326 inline Pixel SDLGetPixel(Bitmap *dst_bitmap, int x, int y)
328 SDL_Surface *surface = dst_bitmap->surface;
330 #ifdef FULLSCREEN_BUG
331 if (dst_bitmap == backbuffer || dst_bitmap == window)
338 switch (surface->format->BytesPerPixel)
340 case 1: /* assuming 8-bpp */
342 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
346 case 2: /* probably 15-bpp or 16-bpp */
348 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
352 case 3: /* slow 24-bpp mode; usually not used */
354 /* does this work? */
355 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
359 shift = surface->format->Rshift;
360 color |= *(pix + shift / 8) >> shift;
361 shift = surface->format->Gshift;
362 color |= *(pix + shift / 8) >> shift;
363 shift = surface->format->Bshift;
364 color |= *(pix + shift / 8) >> shift;
370 case 4: /* probably 32-bpp */
372 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
381 /* ========================================================================= */
382 /* The following functions were taken from the SGE library */
383 /* (SDL Graphics Extension Library) by Anders Lindström */
384 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
385 /* ========================================================================= */
387 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
389 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
391 switch (surface->format->BytesPerPixel)
396 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
402 /* Probably 15-bpp or 16-bpp */
403 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
409 /* Slow 24-bpp mode, usually not used */
413 /* Gack - slow, but endian correct */
414 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
415 shift = surface->format->Rshift;
416 *(pix+shift/8) = color>>shift;
417 shift = surface->format->Gshift;
418 *(pix+shift/8) = color>>shift;
419 shift = surface->format->Bshift;
420 *(pix+shift/8) = color>>shift;
426 /* Probably 32-bpp */
427 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
434 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
435 Uint8 R, Uint8 G, Uint8 B)
437 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
440 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
442 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
445 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
447 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
450 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
455 /* Gack - slow, but endian correct */
456 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
457 shift = surface->format->Rshift;
458 *(pix+shift/8) = color>>shift;
459 shift = surface->format->Gshift;
460 *(pix+shift/8) = color>>shift;
461 shift = surface->format->Bshift;
462 *(pix+shift/8) = color>>shift;
465 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
467 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
470 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
472 switch (dest->format->BytesPerPixel)
475 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
479 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
483 _PutPixel24(dest,x,y,color);
487 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
492 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
494 if (SDL_MUSTLOCK(surface))
496 if (SDL_LockSurface(surface) < 0)
502 _PutPixel(surface, x, y, color);
504 if (SDL_MUSTLOCK(surface))
506 SDL_UnlockSurface(surface);
510 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
511 Uint8 R, Uint8 G, Uint8 B)
513 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
516 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
518 if (y >= 0 && y <= dest->h - 1)
520 switch (dest->format->BytesPerPixel)
523 return y*dest->pitch;
527 return y*dest->pitch/2;
531 return y*dest->pitch;
535 return y*dest->pitch/4;
543 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
545 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
547 switch (surface->format->BytesPerPixel)
552 *((Uint8 *)surface->pixels + ypitch + x) = color;
558 /* Probably 15-bpp or 16-bpp */
559 *((Uint16 *)surface->pixels + ypitch + x) = color;
565 /* Slow 24-bpp mode, usually not used */
569 /* Gack - slow, but endian correct */
570 pix = (Uint8 *)surface->pixels + ypitch + x*3;
571 shift = surface->format->Rshift;
572 *(pix+shift/8) = color>>shift;
573 shift = surface->format->Gshift;
574 *(pix+shift/8) = color>>shift;
575 shift = surface->format->Bshift;
576 *(pix+shift/8) = color>>shift;
582 /* Probably 32-bpp */
583 *((Uint32 *)surface->pixels + ypitch + x) = color;
590 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
595 if (SDL_MUSTLOCK(Surface))
597 if (SDL_LockSurface(Surface) < 0)
610 /* Do the clipping */
611 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
615 if (x2 > Surface->w - 1)
623 SDL_FillRect(Surface, &l, Color);
625 if (SDL_MUSTLOCK(Surface))
627 SDL_UnlockSurface(Surface);
631 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
632 Uint8 R, Uint8 G, Uint8 B)
634 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
637 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
648 /* Do the clipping */
649 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
653 if (x2 > Surface->w - 1)
661 SDL_FillRect(Surface, &l, Color);
664 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
669 if (SDL_MUSTLOCK(Surface))
671 if (SDL_LockSurface(Surface) < 0)
684 /* Do the clipping */
685 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
689 if (y2 > Surface->h - 1)
697 SDL_FillRect(Surface, &l, Color);
699 if (SDL_MUSTLOCK(Surface))
701 SDL_UnlockSurface(Surface);
705 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
706 Uint8 R, Uint8 G, Uint8 B)
708 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
711 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
722 /* Do the clipping */
723 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
727 if (y2 > Surface->h - 1)
735 SDL_FillRect(Surface, &l, Color);
738 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
739 Sint16 x2, Sint16 y2, Uint32 Color,
740 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
743 Sint16 dx, dy, sdx, sdy, x, y, px, py;
748 sdx = (dx < 0) ? -1 : 1;
749 sdy = (dy < 0) ? -1 : 1;
761 for (x = 0; x < dx; x++)
763 Callback(Surface, px, py, Color);
777 for (y = 0; y < dy; y++)
779 Callback(Surface, px, py, Color);
793 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
794 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
795 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
798 sge_DoLine(Surface, X1, Y1, X2, Y2,
799 SDL_MapRGB(Surface->format, R, G, B), Callback);
802 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
805 if (SDL_MUSTLOCK(Surface))
807 if (SDL_LockSurface(Surface) < 0)
812 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
814 /* unlock the display */
815 if (SDL_MUSTLOCK(Surface))
817 SDL_UnlockSurface(Surface);
821 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
822 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
824 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
828 /* ========================================================================= */
829 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
830 /* (Rotozoomer) by Andreas Schiffler */
831 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
832 /* ========================================================================= */
835 -----------------------------------------------------------------------------
838 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
839 -----------------------------------------------------------------------------
850 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
852 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
853 tColorRGBA *sp, *csp, *dp;
857 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
858 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
860 /* allocate memory for row increments */
861 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
862 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
864 /* precalculate row increments */
867 for (x = 0; x <= dst->w; x++)
877 for (y = 0; y <= dst->h; y++)
886 sp = csp = (tColorRGBA *) src->pixels;
887 dp = (tColorRGBA *) dst->pixels;
888 sgap = src->pitch - src->w * 4;
889 dgap = dst->pitch - dst->w * 4;
892 for (y = 0; y < dst->h; y++)
897 for (x = 0; x < dst->w; x++)
902 /* advance source pointers */
906 /* advance destination pointer */
910 /* advance source pointer */
912 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
914 /* advance destination pointers */
915 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
925 -----------------------------------------------------------------------------
928 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
929 -----------------------------------------------------------------------------
932 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
934 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
935 Uint8 *sp, *dp, *csp;
939 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
940 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
942 /* allocate memory for row increments */
943 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
944 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
946 /* precalculate row increments */
949 for (x = 0; x < dst->w; x++)
959 for (y = 0; y < dst->h; y++)
969 for (x = 0; x < dst->w; x++)
977 for (y = 0; y < dst->h; y++)
984 sp = csp = (Uint8 *) src->pixels;
985 dp = (Uint8 *) dst->pixels;
986 dgap = dst->pitch - dst->w;
990 for (y = 0; y < dst->h; y++)
994 for (x = 0; x < dst->w; x++)
999 /* advance source pointers */
1003 /* advance destination pointer */
1007 /* advance source pointer (for row) */
1008 csp += ((*csay) * src->pitch);
1011 /* advance destination pointers */
1022 -----------------------------------------------------------------------------
1025 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1026 'zoomx' and 'zoomy' are scaling factors for width and height.
1027 If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
1028 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1029 into a 32bit RGBA format on the fly.
1030 -----------------------------------------------------------------------------
1033 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1035 SDL_Surface *zoom_src = NULL;
1036 SDL_Surface *zoom_dst = NULL;
1037 boolean is_converted = FALSE;
1044 /* determine if source surface is 32 bit or 8 bit */
1045 is_32bit = (src->format->BitsPerPixel == 32);
1047 if (is_32bit || src->format->BitsPerPixel == 8)
1049 /* use source surface 'as is' */
1054 /* new source surface is 32 bit with a defined RGB ordering */
1055 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1056 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1057 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1059 is_converted = TRUE;
1062 /* allocate surface to completely contain the zoomed surface */
1065 /* target surface is 32 bit with source RGBA/ABGR ordering */
1066 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1067 zoom_src->format->Rmask,
1068 zoom_src->format->Gmask,
1069 zoom_src->format->Bmask, 0);
1073 /* target surface is 8 bit */
1074 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1078 /* lock source surface */
1079 SDL_LockSurface(zoom_src);
1081 /* check which kind of surface we have */
1084 /* call the 32 bit transformation routine to do the zooming */
1085 zoomSurfaceRGBA(zoom_src, zoom_dst);
1090 for (i=0; i < zoom_src->format->palette->ncolors; i++)
1091 zoom_dst->format->palette->colors[i] =
1092 zoom_src->format->palette->colors[i];
1093 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1095 /* call the 8 bit transformation routine to do the zooming */
1096 zoomSurfaceY(zoom_src, zoom_dst);
1099 /* unlock source surface */
1100 SDL_UnlockSurface(zoom_src);
1102 /* free temporary surface */
1104 SDL_FreeSurface(zoom_src);
1106 /* return destination surface */
1110 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1112 SDL_Surface *sdl_surface_tmp;
1113 int dst_width = dst_bitmap->width;
1114 int dst_height = dst_bitmap->height;
1116 /* throw away old destination surface */
1117 SDL_FreeSurface(dst_bitmap->surface);
1119 /* create zoomed temporary surface from source surface */
1120 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1122 /* create native format destination surface from zoomed temporary surface */
1123 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1125 /* free temporary surface */
1126 SDL_FreeSurface(sdl_surface_tmp);
1130 /* ========================================================================= */
1131 /* load image to bitmap */
1132 /* ========================================================================= */
1134 Bitmap *SDLLoadImage(char *filename)
1136 Bitmap *new_bitmap = CreateBitmapStruct();
1137 SDL_Surface *sdl_image_tmp;
1139 /* load image to temporary surface */
1140 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1142 SetError("IMG_Load(): %s", SDL_GetError());
1146 /* create native non-transparent surface for current image */
1147 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1149 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1153 /* create native transparent surface for current image */
1154 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1155 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1156 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1158 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1162 /* free temporary surface */
1163 SDL_FreeSurface(sdl_image_tmp);
1165 new_bitmap->width = new_bitmap->surface->w;
1166 new_bitmap->height = new_bitmap->surface->h;
1172 /* ========================================================================= */
1173 /* audio functions */
1174 /* ========================================================================= */
1176 inline void SDLOpenAudio(void)
1178 if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
1179 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1181 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1183 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1187 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1188 AUDIO_NUM_CHANNELS_STEREO,
1189 setup.system.audio_fragment_size) < 0)
1191 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1195 audio.sound_available = TRUE;
1196 audio.music_available = TRUE;
1197 audio.loops_available = TRUE;
1198 audio.sound_enabled = TRUE;
1200 /* set number of available mixer channels */
1201 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1202 audio.music_channel = MUSIC_CHANNEL;
1203 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1205 Mixer_InitChannels();
1208 inline void SDLCloseAudio(void)
1211 Mix_HaltChannel(-1);
1214 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1218 /* ========================================================================= */
1219 /* event functions */
1220 /* ========================================================================= */
1222 inline void SDLNextEvent(Event *event)
1224 SDL_WaitEvent(event);
1226 #ifdef FULLSCREEN_BUG
1227 if (event->type == EVENT_BUTTONPRESS ||
1228 event->type == EVENT_BUTTONRELEASE)
1230 if (((ButtonEvent *)event)->x > video_xoffset)
1231 ((ButtonEvent *)event)->x -= video_xoffset;
1233 ((ButtonEvent *)event)->x = 0;
1234 if (((ButtonEvent *)event)->y > video_yoffset)
1235 ((ButtonEvent *)event)->y -= video_yoffset;
1237 ((ButtonEvent *)event)->y = 0;
1239 else if (event->type == EVENT_MOTIONNOTIFY)
1241 if (((ButtonEvent *)event)->x > video_xoffset)
1242 ((ButtonEvent *)event)->x -= video_xoffset;
1244 ((ButtonEvent *)event)->x = 0;
1245 if (((ButtonEvent *)event)->y > video_yoffset)
1246 ((ButtonEvent *)event)->y -= video_yoffset;
1248 ((ButtonEvent *)event)->y = 0;
1254 /* ========================================================================= */
1255 /* joystick functions */
1256 /* ========================================================================= */
1258 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1259 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1260 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1262 static boolean SDLOpenJoystick(int nr)
1264 if (nr < 0 || nr > MAX_PLAYERS)
1267 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1270 static void SDLCloseJoystick(int nr)
1272 if (nr < 0 || nr > MAX_PLAYERS)
1275 SDL_JoystickClose(sdl_joystick[nr]);
1278 static boolean SDLCheckJoystickOpened(int nr)
1280 if (nr < 0 || nr > MAX_PLAYERS)
1283 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1286 void HandleJoystickEvent(Event *event)
1290 case SDL_JOYAXISMOTION:
1291 if (event->jaxis.axis < 2)
1292 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1295 case SDL_JOYBUTTONDOWN:
1296 if (event->jbutton.button < 2)
1297 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1300 case SDL_JOYBUTTONUP:
1301 if (event->jbutton.button < 2)
1302 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1310 void SDLInitJoysticks()
1312 static boolean sdl_joystick_subsystem_initialized = FALSE;
1315 if (!sdl_joystick_subsystem_initialized)
1317 sdl_joystick_subsystem_initialized = TRUE;
1319 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1321 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1326 for (i=0; i<MAX_PLAYERS; i++)
1328 char *device_name = setup.input[i].joy.device_name;
1329 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1331 if (joystick_nr >= SDL_NumJoysticks())
1334 /* misuse joystick file descriptor variable to store joystick number */
1335 joystick.fd[i] = joystick_nr;
1337 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1338 if (SDLCheckJoystickOpened(joystick_nr))
1339 SDLCloseJoystick(joystick_nr);
1341 if (!setup.input[i].use_joystick)
1344 if (!SDLOpenJoystick(joystick_nr))
1346 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1350 joystick.status = JOYSTICK_ACTIVATED;
1354 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1356 if (nr < 0 || nr >= MAX_PLAYERS)
1360 *x = sdl_js_axis[nr][0];
1362 *y = sdl_js_axis[nr][1];
1365 *b1 = sdl_js_button[nr][0];
1367 *b2 = sdl_js_button[nr][1];
1372 #endif /* TARGET_SDL */