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 int dst_width = dst_bitmap->width;
1111 int dst_height = dst_bitmap->height;
1113 SDL_FreeSurface(dst_bitmap->surface);
1115 dst_bitmap->surface = zoomSurface(src_bitmap->surface, dst_width,dst_height);
1119 /* ========================================================================= */
1120 /* load image to bitmap */
1121 /* ========================================================================= */
1123 Bitmap *SDLLoadImage(char *filename)
1125 Bitmap *new_bitmap = CreateBitmapStruct();
1126 SDL_Surface *sdl_image_tmp;
1128 /* load image to temporary surface */
1129 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1131 SetError("IMG_Load(): %s", SDL_GetError());
1135 /* create native non-transparent surface for current image */
1136 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1138 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1142 /* create native transparent surface for current image */
1143 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1144 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1145 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1147 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1151 /* free temporary surface */
1152 SDL_FreeSurface(sdl_image_tmp);
1154 new_bitmap->width = new_bitmap->surface->w;
1155 new_bitmap->height = new_bitmap->surface->h;
1161 /* ========================================================================= */
1162 /* audio functions */
1163 /* ========================================================================= */
1165 inline void SDLOpenAudio(void)
1167 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1169 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1173 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1174 AUDIO_NUM_CHANNELS_STEREO,
1175 DEFAULT_AUDIO_FRAGMENT_SIZE) < 0)
1177 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1181 audio.sound_available = TRUE;
1182 audio.music_available = TRUE;
1183 audio.loops_available = TRUE;
1184 audio.sound_enabled = TRUE;
1186 /* set number of available mixer channels */
1187 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1188 audio.music_channel = MUSIC_CHANNEL;
1189 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1191 Mixer_InitChannels();
1194 inline void SDLCloseAudio(void)
1197 Mix_HaltChannel(-1);
1200 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1204 /* ========================================================================= */
1205 /* event functions */
1206 /* ========================================================================= */
1208 inline void SDLNextEvent(Event *event)
1210 SDL_WaitEvent(event);
1212 #ifdef FULLSCREEN_BUG
1213 if (event->type == EVENT_BUTTONPRESS ||
1214 event->type == EVENT_BUTTONRELEASE)
1216 if (((ButtonEvent *)event)->x > video_xoffset)
1217 ((ButtonEvent *)event)->x -= video_xoffset;
1219 ((ButtonEvent *)event)->x = 0;
1220 if (((ButtonEvent *)event)->y > video_yoffset)
1221 ((ButtonEvent *)event)->y -= video_yoffset;
1223 ((ButtonEvent *)event)->y = 0;
1225 else if (event->type == EVENT_MOTIONNOTIFY)
1227 if (((ButtonEvent *)event)->x > video_xoffset)
1228 ((ButtonEvent *)event)->x -= video_xoffset;
1230 ((ButtonEvent *)event)->x = 0;
1231 if (((ButtonEvent *)event)->y > video_yoffset)
1232 ((ButtonEvent *)event)->y -= video_yoffset;
1234 ((ButtonEvent *)event)->y = 0;
1240 /* ========================================================================= */
1241 /* joystick functions */
1242 /* ========================================================================= */
1244 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1245 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1246 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1248 static boolean SDLOpenJoystick(int nr)
1250 if (nr < 0 || nr > MAX_PLAYERS)
1253 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1256 static void SDLCloseJoystick(int nr)
1258 if (nr < 0 || nr > MAX_PLAYERS)
1261 SDL_JoystickClose(sdl_joystick[nr]);
1264 static boolean SDLCheckJoystickOpened(int nr)
1266 if (nr < 0 || nr > MAX_PLAYERS)
1269 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1272 void HandleJoystickEvent(Event *event)
1276 case SDL_JOYAXISMOTION:
1277 if (event->jaxis.axis < 2)
1278 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1281 case SDL_JOYBUTTONDOWN:
1282 if (event->jbutton.button < 2)
1283 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1286 case SDL_JOYBUTTONUP:
1287 if (event->jbutton.button < 2)
1288 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1296 void SDLInitJoysticks()
1298 static boolean sdl_joystick_subsystem_initialized = FALSE;
1301 if (!sdl_joystick_subsystem_initialized)
1303 sdl_joystick_subsystem_initialized = TRUE;
1305 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1307 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1312 for (i=0; i<MAX_PLAYERS; i++)
1314 char *device_name = setup.input[i].joy.device_name;
1315 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1317 if (joystick_nr >= SDL_NumJoysticks())
1320 /* misuse joystick file descriptor variable to store joystick number */
1321 joystick.fd[i] = joystick_nr;
1323 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1324 if (SDLCheckJoystickOpened(joystick_nr))
1325 SDLCloseJoystick(joystick_nr);
1327 if (!setup.input[i].use_joystick)
1330 if (!SDLOpenJoystick(joystick_nr))
1332 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1336 joystick.status = JOYSTICK_ACTIVATED;
1340 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1342 if (nr < 0 || nr >= MAX_PLAYERS)
1346 *x = sdl_js_axis[nr][0];
1348 *y = sdl_js_axis[nr][1];
1351 *b1 = sdl_js_button[nr][0];
1353 *b2 = sdl_js_button[nr][1];
1358 #endif /* TARGET_SDL */