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 /* initialize SDL video */
44 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
45 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
47 /* set default SDL depth */
48 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
51 inline void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
56 static int screen_xy[][2] =
65 /* default: normal game window size */
66 fullscreen_width = video.width;
67 fullscreen_height = video.height;
68 fullscreen_xoffset = 0;
69 fullscreen_yoffset = 0;
72 for (i=0; screen_xy[i][0] != -1; i++)
74 if (video.width <= screen_xy[i][0] && video.height <= screen_xy[i][1])
76 fullscreen_width = screen_xy[i][0];
77 fullscreen_height = screen_xy[i][1];
82 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
83 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
86 /* open SDL video output device (window or fullscreen mode) */
87 if (!SDLSetVideoMode(backbuffer, fullscreen))
88 Error(ERR_EXIT, "setting video mode failed");
90 /* set window and icon title */
91 SDL_WM_SetCaption(program.window_title, program.window_title);
93 /* SDL cannot directly draw to the visible video framebuffer like X11,
94 but always uses a backbuffer, which is then blitted to the visible
95 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
96 visible video framebuffer with 'SDL_Flip', if the hardware supports
97 this). Therefore do not use an additional backbuffer for drawing, but
98 use a symbolic buffer (distinguishable from the SDL backbuffer) called
99 'window', which indicates that the SDL backbuffer should be updated to
100 the visible video framebuffer when attempting to blit to it.
102 For convenience, it seems to be a good idea to create this symbolic
103 buffer 'window' at the same size as the SDL backbuffer. Although it
104 should never be drawn to directly, it would do no harm nevertheless. */
106 /* create additional (symbolic) buffer for double-buffering */
107 *window = CreateBitmap(video.width, video.height, video.depth);
110 inline boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
112 boolean success = TRUE;
113 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
114 int surface_flags_window = SURFACE_FLAGS;
115 SDL_Surface *new_surface = NULL;
117 if (*backbuffer == NULL)
118 *backbuffer = CreateBitmapStruct();
120 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
122 video_xoffset = fullscreen_xoffset;
123 video_yoffset = fullscreen_yoffset;
125 /* switch display to fullscreen mode, if available */
126 if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
127 video.depth, surface_flags_fullscreen))
130 /* switching display to fullscreen mode failed */
131 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
133 /* do not try it again */
134 video.fullscreen_available = FALSE;
139 (*backbuffer)->surface = new_surface;
141 video.fullscreen_enabled = TRUE;
146 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
151 /* switch display to window mode */
152 if ((new_surface = SDL_SetVideoMode(video.width, video.height,
153 video.depth, surface_flags_window))
156 /* switching display to window mode failed -- should not happen */
157 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
163 (*backbuffer)->surface = new_surface;
165 video.fullscreen_enabled = FALSE;
173 inline void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
174 int src_x, int src_y,
175 int width, int height,
176 int dst_x, int dst_y, int copy_mode)
178 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
179 SDL_Rect src_rect, dst_rect;
181 #ifdef FULLSCREEN_BUG
182 if (src_bitmap == backbuffer)
184 src_x += video_xoffset;
185 src_y += video_yoffset;
194 #ifdef FULLSCREEN_BUG
195 if (dst_bitmap == backbuffer || dst_bitmap == window)
197 dst_x += video_xoffset;
198 dst_y += video_yoffset;
207 if (src_bitmap != backbuffer || dst_bitmap != window)
208 SDL_BlitSurface((copy_mode == SDLCOPYAREA_MASKED ?
209 src_bitmap->surface_masked : src_bitmap->surface),
210 &src_rect, real_dst_bitmap->surface, &dst_rect);
212 if (dst_bitmap == window)
213 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
216 inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
217 int width, int height, unsigned int color)
219 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
221 unsigned int color_r = (color >> 16) && 0xff;
222 unsigned int color_g = (color >> 8) && 0xff;
223 unsigned int color_b = (color >> 0) && 0xff;
225 #ifdef FULLSCREEN_BUG
226 if (dst_bitmap == backbuffer || dst_bitmap == window)
238 SDL_FillRect(real_dst_bitmap->surface, &rect,
239 SDL_MapRGB(real_dst_bitmap->surface->format,
240 color_r, color_g, color_b));
242 if (dst_bitmap == window)
243 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
246 inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
247 int to_x, int to_y, unsigned int color)
249 SDL_Surface *surface = dst_bitmap->surface;
251 unsigned int color_r = (color >> 16) & 0xff;
252 unsigned int color_g = (color >> 8) & 0xff;
253 unsigned int color_b = (color >> 0) & 0xff;
256 swap_numbers(&from_x, &to_x);
259 swap_numbers(&from_y, &to_y);
263 rect.w = (to_x - from_x + 1);
264 rect.h = (to_y - from_y + 1);
266 #ifdef FULLSCREEN_BUG
267 if (dst_bitmap == backbuffer || dst_bitmap == window)
269 rect.x += video_xoffset;
270 rect.y += video_yoffset;
274 SDL_FillRect(surface, &rect,
275 SDL_MapRGB(surface->format, color_r, color_g, color_b));
278 inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
279 int to_x, int to_y, Uint32 color)
281 #ifdef FULLSCREEN_BUG
282 if (dst_bitmap == backbuffer || dst_bitmap == window)
284 from_x += video_xoffset;
285 from_y += video_yoffset;
286 to_x += video_xoffset;
287 to_y += video_yoffset;
291 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
295 inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
296 int num_points, Uint32 color)
301 for (i=0; i<num_points - 1; i++)
303 for (x=0; x<line_width; x++)
305 for (y=0; y<line_width; y++)
307 int dx = x - line_width / 2;
308 int dy = y - line_width / 2;
310 if ((x == 0 && y == 0) ||
311 (x == 0 && y == line_width - 1) ||
312 (x == line_width - 1 && y == 0) ||
313 (x == line_width - 1 && y == line_width - 1))
316 sge_Line(surface, points[i].x + dx, points[i].y + dy,
317 points[i+1].x + dx, points[i+1].y + dy, color);
324 inline Pixel SDLGetPixel(Bitmap *dst_bitmap, int x, int y)
326 SDL_Surface *surface = dst_bitmap->surface;
328 #ifdef FULLSCREEN_BUG
329 if (dst_bitmap == backbuffer || dst_bitmap == window)
336 switch (surface->format->BytesPerPixel)
338 case 1: /* assuming 8-bpp */
340 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
344 case 2: /* probably 15-bpp or 16-bpp */
346 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
350 case 3: /* slow 24-bpp mode; usually not used */
352 /* does this work? */
353 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
357 shift = surface->format->Rshift;
358 color |= *(pix + shift / 8) >> shift;
359 shift = surface->format->Gshift;
360 color |= *(pix + shift / 8) >> shift;
361 shift = surface->format->Bshift;
362 color |= *(pix + shift / 8) >> shift;
368 case 4: /* probably 32-bpp */
370 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
379 /* ========================================================================= */
380 /* The following functions were taken from the SGE library */
381 /* (SDL Graphics Extension Library) by Anders Lindström */
382 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
383 /* ========================================================================= */
385 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
387 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
389 switch (surface->format->BytesPerPixel)
394 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
400 /* Probably 15-bpp or 16-bpp */
401 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
407 /* Slow 24-bpp mode, usually not used */
411 /* Gack - slow, but endian correct */
412 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
413 shift = surface->format->Rshift;
414 *(pix+shift/8) = color>>shift;
415 shift = surface->format->Gshift;
416 *(pix+shift/8) = color>>shift;
417 shift = surface->format->Bshift;
418 *(pix+shift/8) = color>>shift;
424 /* Probably 32-bpp */
425 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
432 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
433 Uint8 R, Uint8 G, Uint8 B)
435 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
438 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
440 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
443 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
445 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
448 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
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;
463 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
465 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
468 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
470 switch (dest->format->BytesPerPixel)
473 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
477 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
481 _PutPixel24(dest,x,y,color);
485 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
490 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
492 if (SDL_MUSTLOCK(surface))
494 if (SDL_LockSurface(surface) < 0)
500 _PutPixel(surface, x, y, color);
502 if (SDL_MUSTLOCK(surface))
504 SDL_UnlockSurface(surface);
508 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
509 Uint8 R, Uint8 G, Uint8 B)
511 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
514 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
516 if (y >= 0 && y <= dest->h - 1)
518 switch (dest->format->BytesPerPixel)
521 return y*dest->pitch;
525 return y*dest->pitch/2;
529 return y*dest->pitch;
533 return y*dest->pitch/4;
541 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
543 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
545 switch (surface->format->BytesPerPixel)
550 *((Uint8 *)surface->pixels + ypitch + x) = color;
556 /* Probably 15-bpp or 16-bpp */
557 *((Uint16 *)surface->pixels + ypitch + x) = color;
563 /* Slow 24-bpp mode, usually not used */
567 /* Gack - slow, but endian correct */
568 pix = (Uint8 *)surface->pixels + ypitch + x*3;
569 shift = surface->format->Rshift;
570 *(pix+shift/8) = color>>shift;
571 shift = surface->format->Gshift;
572 *(pix+shift/8) = color>>shift;
573 shift = surface->format->Bshift;
574 *(pix+shift/8) = color>>shift;
580 /* Probably 32-bpp */
581 *((Uint32 *)surface->pixels + ypitch + x) = color;
588 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
593 if (SDL_MUSTLOCK(Surface))
595 if (SDL_LockSurface(Surface) < 0)
608 /* Do the clipping */
609 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
613 if (x2 > Surface->w - 1)
621 SDL_FillRect(Surface, &l, Color);
623 if (SDL_MUSTLOCK(Surface))
625 SDL_UnlockSurface(Surface);
629 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
630 Uint8 R, Uint8 G, Uint8 B)
632 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
635 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
646 /* Do the clipping */
647 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
651 if (x2 > Surface->w - 1)
659 SDL_FillRect(Surface, &l, Color);
662 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
667 if (SDL_MUSTLOCK(Surface))
669 if (SDL_LockSurface(Surface) < 0)
682 /* Do the clipping */
683 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
687 if (y2 > Surface->h - 1)
695 SDL_FillRect(Surface, &l, Color);
697 if (SDL_MUSTLOCK(Surface))
699 SDL_UnlockSurface(Surface);
703 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
704 Uint8 R, Uint8 G, Uint8 B)
706 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
709 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
720 /* Do the clipping */
721 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
725 if (y2 > Surface->h - 1)
733 SDL_FillRect(Surface, &l, Color);
736 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
737 Sint16 x2, Sint16 y2, Uint32 Color,
738 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
741 Sint16 dx, dy, sdx, sdy, x, y, px, py;
746 sdx = (dx < 0) ? -1 : 1;
747 sdy = (dy < 0) ? -1 : 1;
759 for (x = 0; x < dx; x++)
761 Callback(Surface, px, py, Color);
775 for (y = 0; y < dy; y++)
777 Callback(Surface, px, py, Color);
791 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
792 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
793 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
796 sge_DoLine(Surface, X1, Y1, X2, Y2,
797 SDL_MapRGB(Surface->format, R, G, B), Callback);
800 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
803 if (SDL_MUSTLOCK(Surface))
805 if (SDL_LockSurface(Surface) < 0)
810 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
812 /* unlock the display */
813 if (SDL_MUSTLOCK(Surface))
815 SDL_UnlockSurface(Surface);
819 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
820 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
822 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
826 /* ========================================================================= */
827 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
828 /* (Rotozoomer) by Andreas Schiffler */
829 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
830 /* ========================================================================= */
841 -----------------------------------------------------------------------------
844 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
845 -----------------------------------------------------------------------------
848 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
850 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
851 tColorRGBA *sp, *csp, *dp;
855 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
856 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
858 /* allocate memory for row increments */
859 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
860 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
862 /* precalculate row increments */
865 for (x = 0; x <= dst->w; x++)
875 for (y = 0; y <= dst->h; y++)
884 sp = csp = (tColorRGBA *) src->pixels;
885 dp = (tColorRGBA *) dst->pixels;
886 sgap = src->pitch - src->w * 4;
887 dgap = dst->pitch - dst->w * 4;
890 for (y = 0; y < dst->h; y++)
895 for (x = 0; x < dst->w; x++)
900 /* advance source pointers */
904 /* advance destination pointer */
908 /* advance source pointer */
910 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
912 /* advance destination pointers */
913 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
923 -----------------------------------------------------------------------------
926 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
927 -----------------------------------------------------------------------------
930 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
932 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
933 Uint8 *sp, *dp, *csp;
937 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
938 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
940 /* allocate memory for row increments */
941 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
942 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
944 /* precalculate row increments */
947 for (x = 0; x < dst->w; x++)
957 for (y = 0; y < dst->h; y++)
967 for (x = 0; x < dst->w; x++)
975 for (y = 0; y < dst->h; y++)
982 sp = csp = (Uint8 *) src->pixels;
983 dp = (Uint8 *) dst->pixels;
984 dgap = dst->pitch - dst->w;
988 for (y = 0; y < dst->h; y++)
992 for (x = 0; x < dst->w; x++)
997 /* advance source pointers */
1001 /* advance destination pointer */
1005 /* advance source pointer (for row) */
1006 csp += ((*csay) * src->pitch);
1009 /* advance destination pointers */
1020 -----------------------------------------------------------------------------
1023 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1024 'zoomx' and 'zoomy' are scaling factors for width and height.
1025 If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
1026 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1027 into a 32bit RGBA format on the fly.
1028 -----------------------------------------------------------------------------
1031 void zoomSurfaceSize(int width, int height, float zoom_x, float zoom_y,
1032 int *dst_width, int *dst_height)
1034 const float value_limit = 0.001;
1036 /* sanity check zoom factors */
1037 if (zoom_x < value_limit)
1038 zoom_x = value_limit;
1039 if (zoom_y < value_limit)
1040 zoom_y = value_limit;
1042 /* calculate target size */
1043 *dst_width = (int) ((float) width * zoom_x);
1044 *dst_height = (int) ((float) height * zoom_y);
1048 if (*dst_height < 1)
1052 SDL_Surface *zoomSurface(SDL_Surface *src, float zoom_x, float zoom_y)
1054 SDL_Surface *zoom_src = NULL;
1055 SDL_Surface *zoom_dst = NULL;
1056 int dst_width, dst_height;
1057 boolean is_converted = FALSE;
1064 /* determine if source surface is 32 bit or 8 bit */
1065 is_32bit = (src->format->BitsPerPixel == 32);
1067 if (is_32bit || src->format->BitsPerPixel == 8)
1069 /* use source surface 'as is' */
1074 /* new source surface is 32 bit with a defined RGB ordering */
1075 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1076 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1077 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1079 is_converted = TRUE;
1082 /* get size of destination surface */
1083 zoomSurfaceSize(zoom_src->w, zoom_src->h, zoom_x, zoom_y,
1084 &dst_width, &dst_height);
1086 /* allocate surface to completely contain the zoomed surface */
1089 /* target surface is 32 bit with source RGBA/ABGR ordering */
1090 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1091 zoom_src->format->Rmask,
1092 zoom_src->format->Gmask,
1093 zoom_src->format->Bmask, 0);
1097 /* target surface is 8 bit */
1098 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1102 /* lock source surface */
1103 SDL_LockSurface(zoom_src);
1105 /* check which kind of surface we have */
1108 /* call the 32 bit transformation routine to do the zooming */
1109 zoomSurfaceRGBA(zoom_src, zoom_dst);
1114 for (i=0; i < zoom_src->format->palette->ncolors; i++)
1115 zoom_dst->format->palette->colors[i] =
1116 zoom_src->format->palette->colors[i];
1117 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1119 /* call the 8 bit transformation routine to do the zooming */
1120 zoomSurfaceY(zoom_src, zoom_dst);
1123 /* unlock source surface */
1124 SDL_UnlockSurface(zoom_src);
1126 /* free temporary surface */
1128 SDL_FreeSurface(zoom_src);
1130 /* return destination surface */
1134 SDL_Surface *SDLZoomSurface(SDL_Surface *src, float zoom_x, float zoom_y)
1136 return zoomSurface(src, zoom_x, zoom_y);
1140 /* ========================================================================= */
1141 /* load image to bitmap */
1142 /* ========================================================================= */
1144 Bitmap *SDLLoadImage(char *filename)
1146 Bitmap *new_bitmap = CreateBitmapStruct();
1147 SDL_Surface *sdl_image_tmp;
1149 /* load image to temporary surface */
1150 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1152 SetError("IMG_Load(): %s", SDL_GetError());
1156 /* create native non-transparent surface for current image */
1157 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1159 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1163 /* create native transparent surface for current image */
1164 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1165 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1166 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1168 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1172 /* free temporary surface */
1173 SDL_FreeSurface(sdl_image_tmp);
1175 new_bitmap->width = new_bitmap->surface->w;
1176 new_bitmap->height = new_bitmap->surface->h;
1182 /* ========================================================================= */
1183 /* audio functions */
1184 /* ========================================================================= */
1186 inline void SDLOpenAudio(void)
1188 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1190 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1194 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1195 AUDIO_NUM_CHANNELS_STEREO,
1196 DEFAULT_AUDIO_FRAGMENT_SIZE) < 0)
1198 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1202 audio.sound_available = TRUE;
1203 audio.music_available = TRUE;
1204 audio.loops_available = TRUE;
1205 audio.sound_enabled = TRUE;
1207 /* set number of available mixer channels */
1208 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1209 audio.music_channel = MUSIC_CHANNEL;
1210 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1212 Mixer_InitChannels();
1215 inline void SDLCloseAudio(void)
1218 Mix_HaltChannel(-1);
1221 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1225 /* ========================================================================= */
1226 /* event functions */
1227 /* ========================================================================= */
1229 inline void SDLNextEvent(Event *event)
1231 SDL_WaitEvent(event);
1233 #ifdef FULLSCREEN_BUG
1234 if (event->type == EVENT_BUTTONPRESS ||
1235 event->type == EVENT_BUTTONRELEASE)
1237 if (((ButtonEvent *)event)->x > video_xoffset)
1238 ((ButtonEvent *)event)->x -= video_xoffset;
1240 ((ButtonEvent *)event)->x = 0;
1241 if (((ButtonEvent *)event)->y > video_yoffset)
1242 ((ButtonEvent *)event)->y -= video_yoffset;
1244 ((ButtonEvent *)event)->y = 0;
1246 else if (event->type == EVENT_MOTIONNOTIFY)
1248 if (((ButtonEvent *)event)->x > video_xoffset)
1249 ((ButtonEvent *)event)->x -= video_xoffset;
1251 ((ButtonEvent *)event)->x = 0;
1252 if (((ButtonEvent *)event)->y > video_yoffset)
1253 ((ButtonEvent *)event)->y -= video_yoffset;
1255 ((ButtonEvent *)event)->y = 0;
1261 /* ========================================================================= */
1262 /* joystick functions */
1263 /* ========================================================================= */
1265 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1266 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1267 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1269 static boolean SDLOpenJoystick(int nr)
1271 if (nr < 0 || nr > MAX_PLAYERS)
1274 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1277 static void SDLCloseJoystick(int nr)
1279 if (nr < 0 || nr > MAX_PLAYERS)
1282 SDL_JoystickClose(sdl_joystick[nr]);
1285 static boolean SDLCheckJoystickOpened(int nr)
1287 if (nr < 0 || nr > MAX_PLAYERS)
1290 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1293 void HandleJoystickEvent(Event *event)
1297 case SDL_JOYAXISMOTION:
1298 if (event->jaxis.axis < 2)
1299 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1302 case SDL_JOYBUTTONDOWN:
1303 if (event->jbutton.button < 2)
1304 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1307 case SDL_JOYBUTTONUP:
1308 if (event->jbutton.button < 2)
1309 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1317 void SDLInitJoysticks()
1319 static boolean sdl_joystick_subsystem_initialized = FALSE;
1322 if (!sdl_joystick_subsystem_initialized)
1324 sdl_joystick_subsystem_initialized = TRUE;
1326 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1328 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1333 for (i=0; i<MAX_PLAYERS; i++)
1335 char *device_name = setup.input[i].joy.device_name;
1336 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1338 if (joystick_nr >= SDL_NumJoysticks())
1341 /* misuse joystick file descriptor variable to store joystick number */
1342 joystick.fd[i] = joystick_nr;
1344 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1345 if (SDLCheckJoystickOpened(joystick_nr))
1346 SDLCloseJoystick(joystick_nr);
1348 if (!setup.input[i].use_joystick)
1351 if (!SDLOpenJoystick(joystick_nr))
1353 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1357 joystick.status = JOYSTICK_ACTIVATED;
1361 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1363 if (nr < 0 || nr >= MAX_PLAYERS)
1367 *x = sdl_js_axis[nr][0];
1369 *y = sdl_js_axis[nr][1];
1372 *b1 = sdl_js_button[nr][0];
1374 *b2 = sdl_js_button[nr][1];
1379 #endif /* TARGET_SDL */