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 /* ========================================================================= */
833 -----------------------------------------------------------------------------
836 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
837 -----------------------------------------------------------------------------
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 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1033 SDL_Surface *zoom_src = NULL;
1034 SDL_Surface *zoom_dst = NULL;
1035 boolean is_converted = FALSE;
1042 /* determine if source surface is 32 bit or 8 bit */
1043 is_32bit = (src->format->BitsPerPixel == 32);
1045 if (is_32bit || src->format->BitsPerPixel == 8)
1047 /* use source surface 'as is' */
1052 /* new source surface is 32 bit with a defined RGB ordering */
1053 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1054 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1055 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1057 is_converted = TRUE;
1060 /* allocate surface to completely contain the zoomed surface */
1063 /* target surface is 32 bit with source RGBA/ABGR ordering */
1064 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1065 zoom_src->format->Rmask,
1066 zoom_src->format->Gmask,
1067 zoom_src->format->Bmask, 0);
1071 /* target surface is 8 bit */
1072 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1076 /* lock source surface */
1077 SDL_LockSurface(zoom_src);
1079 /* check which kind of surface we have */
1082 /* call the 32 bit transformation routine to do the zooming */
1083 zoomSurfaceRGBA(zoom_src, zoom_dst);
1088 for (i=0; i < zoom_src->format->palette->ncolors; i++)
1089 zoom_dst->format->palette->colors[i] =
1090 zoom_src->format->palette->colors[i];
1091 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1093 /* call the 8 bit transformation routine to do the zooming */
1094 zoomSurfaceY(zoom_src, zoom_dst);
1097 /* unlock source surface */
1098 SDL_UnlockSurface(zoom_src);
1100 /* free temporary surface */
1102 SDL_FreeSurface(zoom_src);
1104 /* return destination surface */
1108 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1110 SDL_Surface *sdl_surface_tmp;
1111 int dst_width = dst_bitmap->width;
1112 int dst_height = dst_bitmap->height;
1114 /* throw away old destination surface */
1115 SDL_FreeSurface(dst_bitmap->surface);
1117 /* create zoomed temporary surface from source surface */
1118 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1120 /* create native format destination surface from zoomed temporary surface */
1121 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1123 /* free temporary surface */
1124 SDL_FreeSurface(sdl_surface_tmp);
1128 /* ========================================================================= */
1129 /* load image to bitmap */
1130 /* ========================================================================= */
1132 Bitmap *SDLLoadImage(char *filename)
1134 Bitmap *new_bitmap = CreateBitmapStruct();
1135 SDL_Surface *sdl_image_tmp;
1137 /* load image to temporary surface */
1138 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1140 SetError("IMG_Load(): %s", SDL_GetError());
1144 /* create native non-transparent surface for current image */
1145 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1147 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1151 /* create native transparent surface for current image */
1152 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1153 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1154 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1156 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1160 /* free temporary surface */
1161 SDL_FreeSurface(sdl_image_tmp);
1163 new_bitmap->width = new_bitmap->surface->w;
1164 new_bitmap->height = new_bitmap->surface->h;
1170 /* ========================================================================= */
1171 /* audio functions */
1172 /* ========================================================================= */
1174 inline void SDLOpenAudio(void)
1176 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1178 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1182 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1183 AUDIO_NUM_CHANNELS_STEREO,
1184 DEFAULT_AUDIO_FRAGMENT_SIZE) < 0)
1186 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1190 audio.sound_available = TRUE;
1191 audio.music_available = TRUE;
1192 audio.loops_available = TRUE;
1193 audio.sound_enabled = TRUE;
1195 /* set number of available mixer channels */
1196 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1197 audio.music_channel = MUSIC_CHANNEL;
1198 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1200 Mixer_InitChannels();
1203 inline void SDLCloseAudio(void)
1206 Mix_HaltChannel(-1);
1209 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1213 /* ========================================================================= */
1214 /* event functions */
1215 /* ========================================================================= */
1217 inline void SDLNextEvent(Event *event)
1219 SDL_WaitEvent(event);
1221 #ifdef FULLSCREEN_BUG
1222 if (event->type == EVENT_BUTTONPRESS ||
1223 event->type == EVENT_BUTTONRELEASE)
1225 if (((ButtonEvent *)event)->x > video_xoffset)
1226 ((ButtonEvent *)event)->x -= video_xoffset;
1228 ((ButtonEvent *)event)->x = 0;
1229 if (((ButtonEvent *)event)->y > video_yoffset)
1230 ((ButtonEvent *)event)->y -= video_yoffset;
1232 ((ButtonEvent *)event)->y = 0;
1234 else if (event->type == EVENT_MOTIONNOTIFY)
1236 if (((ButtonEvent *)event)->x > video_xoffset)
1237 ((ButtonEvent *)event)->x -= video_xoffset;
1239 ((ButtonEvent *)event)->x = 0;
1240 if (((ButtonEvent *)event)->y > video_yoffset)
1241 ((ButtonEvent *)event)->y -= video_yoffset;
1243 ((ButtonEvent *)event)->y = 0;
1249 /* ========================================================================= */
1250 /* joystick functions */
1251 /* ========================================================================= */
1253 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1254 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1255 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1257 static boolean SDLOpenJoystick(int nr)
1259 if (nr < 0 || nr > MAX_PLAYERS)
1262 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1265 static void SDLCloseJoystick(int nr)
1267 if (nr < 0 || nr > MAX_PLAYERS)
1270 SDL_JoystickClose(sdl_joystick[nr]);
1273 static boolean SDLCheckJoystickOpened(int nr)
1275 if (nr < 0 || nr > MAX_PLAYERS)
1278 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1281 void HandleJoystickEvent(Event *event)
1285 case SDL_JOYAXISMOTION:
1286 if (event->jaxis.axis < 2)
1287 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1290 case SDL_JOYBUTTONDOWN:
1291 if (event->jbutton.button < 2)
1292 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1295 case SDL_JOYBUTTONUP:
1296 if (event->jbutton.button < 2)
1297 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1305 void SDLInitJoysticks()
1307 static boolean sdl_joystick_subsystem_initialized = FALSE;
1310 if (!sdl_joystick_subsystem_initialized)
1312 sdl_joystick_subsystem_initialized = TRUE;
1314 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1316 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1321 for (i=0; i<MAX_PLAYERS; i++)
1323 char *device_name = setup.input[i].joy.device_name;
1324 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1326 if (joystick_nr >= SDL_NumJoysticks())
1329 /* misuse joystick file descriptor variable to store joystick number */
1330 joystick.fd[i] = joystick_nr;
1332 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1333 if (SDLCheckJoystickOpened(joystick_nr))
1334 SDLCloseJoystick(joystick_nr);
1336 if (!setup.input[i].use_joystick)
1339 if (!SDLOpenJoystick(joystick_nr))
1341 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1345 joystick.status = JOYSTICK_ACTIVATED;
1349 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1351 if (nr < 0 || nr >= MAX_PLAYERS)
1355 *x = sdl_js_axis[nr][0];
1357 *y = sdl_js_axis[nr][1];
1360 *b1 = sdl_js_button[nr][0];
1362 *b2 = sdl_js_button[nr][1];
1367 #endif /* TARGET_SDL */