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);
29 /* #ifdef PLATFORM_WIN32 */
30 #define FULLSCREEN_BUG
33 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
34 static int fullscreen_width;
35 static int fullscreen_height;
36 static int fullscreen_xoffset;
37 static int fullscreen_yoffset;
38 static int video_xoffset;
39 static int video_yoffset;
41 inline void SDLInitVideoDisplay(void)
43 putenv("SDL_VIDEO_CENTERED=1");
45 /* initialize SDL video */
46 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
47 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
49 /* set default SDL depth */
50 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
53 inline void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
58 static int screen_xy[][2] =
67 /* default: normal game window size */
68 fullscreen_width = video.width;
69 fullscreen_height = video.height;
70 fullscreen_xoffset = 0;
71 fullscreen_yoffset = 0;
74 for (i = 0; screen_xy[i][0] != -1; i++)
76 if (video.width <= screen_xy[i][0] && video.height <= screen_xy[i][1])
78 fullscreen_width = screen_xy[i][0];
79 fullscreen_height = screen_xy[i][1];
84 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
85 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
88 /* open SDL video output device (window or fullscreen mode) */
89 if (!SDLSetVideoMode(backbuffer, fullscreen))
90 Error(ERR_EXIT, "setting video mode failed");
92 /* set window and icon title */
93 SDL_WM_SetCaption(program.window_title, program.window_title);
95 /* SDL cannot directly draw to the visible video framebuffer like X11,
96 but always uses a backbuffer, which is then blitted to the visible
97 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
98 visible video framebuffer with 'SDL_Flip', if the hardware supports
99 this). Therefore do not use an additional backbuffer for drawing, but
100 use a symbolic buffer (distinguishable from the SDL backbuffer) called
101 'window', which indicates that the SDL backbuffer should be updated to
102 the visible video framebuffer when attempting to blit to it.
104 For convenience, it seems to be a good idea to create this symbolic
105 buffer 'window' at the same size as the SDL backbuffer. Although it
106 should never be drawn to directly, it would do no harm nevertheless. */
108 /* create additional (symbolic) buffer for double-buffering */
109 *window = CreateBitmap(video.width, video.height, video.depth);
112 inline boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
114 boolean success = TRUE;
115 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
116 int surface_flags_window = SURFACE_FLAGS;
117 SDL_Surface *new_surface = NULL;
119 if (*backbuffer == NULL)
120 *backbuffer = CreateBitmapStruct();
122 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
124 video_xoffset = fullscreen_xoffset;
125 video_yoffset = fullscreen_yoffset;
127 /* switch display to fullscreen mode, if available */
128 if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
129 video.depth, surface_flags_fullscreen))
132 /* switching display to fullscreen mode failed */
133 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
135 /* do not try it again */
136 video.fullscreen_available = FALSE;
141 (*backbuffer)->surface = new_surface;
143 video.fullscreen_enabled = TRUE;
148 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
153 /* switch display to window mode */
154 if ((new_surface = SDL_SetVideoMode(video.width, video.height,
155 video.depth, surface_flags_window))
158 /* switching display to window mode failed -- should not happen */
159 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
165 (*backbuffer)->surface = new_surface;
167 video.fullscreen_enabled = FALSE;
175 inline void SDLCreateBitmapContent(Bitmap *new_bitmap,
176 int width, int height, int depth)
178 SDL_Surface *surface_tmp, *surface_native;
180 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
183 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
185 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
186 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
188 SDL_FreeSurface(surface_tmp);
190 new_bitmap->surface = surface_native;
193 inline void SDLFreeBitmapPointers(Bitmap *bitmap)
196 SDL_FreeSurface(bitmap->surface);
197 if (bitmap->surface_masked)
198 SDL_FreeSurface(bitmap->surface_masked);
199 bitmap->surface = NULL;
200 bitmap->surface_masked = NULL;
203 inline void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
204 int src_x, int src_y,
205 int width, int height,
206 int dst_x, int dst_y, int mask_mode)
208 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
209 SDL_Rect src_rect, dst_rect;
211 #ifdef FULLSCREEN_BUG
212 if (src_bitmap == backbuffer)
214 src_x += video_xoffset;
215 src_y += video_yoffset;
224 #ifdef FULLSCREEN_BUG
225 if (dst_bitmap == backbuffer || dst_bitmap == window)
227 dst_x += video_xoffset;
228 dst_y += video_yoffset;
237 if (src_bitmap != backbuffer || dst_bitmap != window)
238 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
239 src_bitmap->surface_masked : src_bitmap->surface),
240 &src_rect, real_dst_bitmap->surface, &dst_rect);
242 if (dst_bitmap == window)
243 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
246 inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
247 int width, int height, Uint32 color)
249 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
252 unsigned int color_r = (color >> 16) & 0xff;
253 unsigned int color_g = (color >> 8) & 0xff;
254 unsigned int color_b = (color >> 0) & 0xff;
257 #ifdef FULLSCREEN_BUG
258 if (dst_bitmap == backbuffer || dst_bitmap == window)
271 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
273 SDL_FillRect(real_dst_bitmap->surface, &rect,
274 SDL_MapRGB(real_dst_bitmap->surface->format,
275 color_r, color_g, color_b));
278 if (dst_bitmap == window)
279 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
282 inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
283 int to_x, int to_y, Uint32 color)
285 SDL_Surface *surface = dst_bitmap->surface;
288 unsigned int color_r = (color >> 16) & 0xff;
289 unsigned int color_g = (color >> 8) & 0xff;
290 unsigned int color_b = (color >> 0) & 0xff;
294 swap_numbers(&from_x, &to_x);
297 swap_numbers(&from_y, &to_y);
301 rect.w = (to_x - from_x + 1);
302 rect.h = (to_y - from_y + 1);
304 #ifdef FULLSCREEN_BUG
305 if (dst_bitmap == backbuffer || dst_bitmap == window)
307 rect.x += video_xoffset;
308 rect.y += video_yoffset;
313 SDL_FillRect(surface, &rect, color);
315 SDL_FillRect(surface, &rect,
316 SDL_MapRGB(surface->format, color_r, color_g, color_b));
320 inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
321 int to_x, int to_y, Uint32 color)
323 #ifdef FULLSCREEN_BUG
324 if (dst_bitmap == backbuffer || dst_bitmap == window)
326 from_x += video_xoffset;
327 from_y += video_yoffset;
328 to_x += video_xoffset;
329 to_y += video_yoffset;
333 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
337 inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
338 int num_points, Uint32 color)
343 for (i = 0; i < num_points - 1; i++)
345 for (x = 0; x < line_width; x++)
347 for (y = 0; y < line_width; y++)
349 int dx = x - line_width / 2;
350 int dy = y - line_width / 2;
352 if ((x == 0 && y == 0) ||
353 (x == 0 && y == line_width - 1) ||
354 (x == line_width - 1 && y == 0) ||
355 (x == line_width - 1 && y == line_width - 1))
358 sge_Line(surface, points[i].x + dx, points[i].y + dy,
359 points[i+1].x + dx, points[i+1].y + dy, color);
366 inline Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
368 SDL_Surface *surface = src_bitmap->surface;
370 #ifdef FULLSCREEN_BUG
371 if (src_bitmap == backbuffer || src_bitmap == window)
378 switch (surface->format->BytesPerPixel)
380 case 1: /* assuming 8-bpp */
382 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
386 case 2: /* probably 15-bpp or 16-bpp */
388 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
392 case 3: /* slow 24-bpp mode; usually not used */
394 /* does this work? */
395 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
399 shift = surface->format->Rshift;
400 color |= *(pix + shift / 8) >> shift;
401 shift = surface->format->Gshift;
402 color |= *(pix + shift / 8) >> shift;
403 shift = surface->format->Bshift;
404 color |= *(pix + shift / 8) >> shift;
410 case 4: /* probably 32-bpp */
412 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
421 /* ========================================================================= */
422 /* The following functions were taken from the SGE library */
423 /* (SDL Graphics Extension Library) by Anders Lindström */
424 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
425 /* ========================================================================= */
427 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
429 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
431 switch (surface->format->BytesPerPixel)
436 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
442 /* Probably 15-bpp or 16-bpp */
443 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
449 /* Slow 24-bpp mode, usually not used */
453 /* Gack - slow, but endian correct */
454 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
455 shift = surface->format->Rshift;
456 *(pix+shift/8) = color>>shift;
457 shift = surface->format->Gshift;
458 *(pix+shift/8) = color>>shift;
459 shift = surface->format->Bshift;
460 *(pix+shift/8) = color>>shift;
466 /* Probably 32-bpp */
467 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
474 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
475 Uint8 R, Uint8 G, Uint8 B)
477 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
480 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
482 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
485 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
487 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
490 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
495 /* Gack - slow, but endian correct */
496 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
497 shift = surface->format->Rshift;
498 *(pix+shift/8) = color>>shift;
499 shift = surface->format->Gshift;
500 *(pix+shift/8) = color>>shift;
501 shift = surface->format->Bshift;
502 *(pix+shift/8) = color>>shift;
505 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
507 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
510 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
512 switch (dest->format->BytesPerPixel)
515 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
519 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
523 _PutPixel24(dest,x,y,color);
527 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
532 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
534 if (SDL_MUSTLOCK(surface))
536 if (SDL_LockSurface(surface) < 0)
542 _PutPixel(surface, x, y, color);
544 if (SDL_MUSTLOCK(surface))
546 SDL_UnlockSurface(surface);
550 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
551 Uint8 r, Uint8 g, Uint8 b)
553 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
556 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
558 if (y >= 0 && y <= dest->h - 1)
560 switch (dest->format->BytesPerPixel)
563 return y*dest->pitch;
567 return y*dest->pitch/2;
571 return y*dest->pitch;
575 return y*dest->pitch/4;
583 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
585 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
587 switch (surface->format->BytesPerPixel)
592 *((Uint8 *)surface->pixels + ypitch + x) = color;
598 /* Probably 15-bpp or 16-bpp */
599 *((Uint16 *)surface->pixels + ypitch + x) = color;
605 /* Slow 24-bpp mode, usually not used */
609 /* Gack - slow, but endian correct */
610 pix = (Uint8 *)surface->pixels + ypitch + x*3;
611 shift = surface->format->Rshift;
612 *(pix+shift/8) = color>>shift;
613 shift = surface->format->Gshift;
614 *(pix+shift/8) = color>>shift;
615 shift = surface->format->Bshift;
616 *(pix+shift/8) = color>>shift;
622 /* Probably 32-bpp */
623 *((Uint32 *)surface->pixels + ypitch + x) = color;
630 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
635 if (SDL_MUSTLOCK(Surface))
637 if (SDL_LockSurface(Surface) < 0)
650 /* Do the clipping */
651 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
655 if (x2 > Surface->w - 1)
663 SDL_FillRect(Surface, &l, Color);
665 if (SDL_MUSTLOCK(Surface))
667 SDL_UnlockSurface(Surface);
671 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
672 Uint8 R, Uint8 G, Uint8 B)
674 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
677 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
688 /* Do the clipping */
689 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
693 if (x2 > Surface->w - 1)
701 SDL_FillRect(Surface, &l, Color);
704 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
709 if (SDL_MUSTLOCK(Surface))
711 if (SDL_LockSurface(Surface) < 0)
724 /* Do the clipping */
725 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
729 if (y2 > Surface->h - 1)
737 SDL_FillRect(Surface, &l, Color);
739 if (SDL_MUSTLOCK(Surface))
741 SDL_UnlockSurface(Surface);
745 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
746 Uint8 R, Uint8 G, Uint8 B)
748 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
751 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
762 /* Do the clipping */
763 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
767 if (y2 > Surface->h - 1)
775 SDL_FillRect(Surface, &l, Color);
778 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
779 Sint16 x2, Sint16 y2, Uint32 Color,
780 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
783 Sint16 dx, dy, sdx, sdy, x, y, px, py;
788 sdx = (dx < 0) ? -1 : 1;
789 sdy = (dy < 0) ? -1 : 1;
801 for (x = 0; x < dx; x++)
803 Callback(Surface, px, py, Color);
817 for (y = 0; y < dy; y++)
819 Callback(Surface, px, py, Color);
833 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
834 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
835 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
838 sge_DoLine(Surface, X1, Y1, X2, Y2,
839 SDL_MapRGB(Surface->format, R, G, B), Callback);
842 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
845 if (SDL_MUSTLOCK(Surface))
847 if (SDL_LockSurface(Surface) < 0)
852 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
854 /* unlock the display */
855 if (SDL_MUSTLOCK(Surface))
857 SDL_UnlockSurface(Surface);
861 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
862 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
864 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
867 inline void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
869 #ifdef FULLSCREEN_BUG
870 if (dst_bitmap == backbuffer || dst_bitmap == window)
877 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
882 -----------------------------------------------------------------------------
883 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
884 -----------------------------------------------------------------------------
887 inline void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
888 int width, int height, Uint32 color)
892 for (y = src_y; y < src_y + height; y++)
894 for (x = src_x; x < src_x + width; x++)
896 Uint32 pixel = SDLGetPixel(bitmap, x, y);
898 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
903 inline void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
904 int src_x, int src_y, int width, int height,
905 int dst_x, int dst_y)
909 for (y = 0; y < height; y++)
911 for (x = 0; x < width; x++)
913 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
915 if (pixel != BLACK_PIXEL)
916 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
922 /* ========================================================================= */
923 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
924 /* (Rotozoomer) by Andreas Schiffler */
925 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
926 /* ========================================================================= */
929 -----------------------------------------------------------------------------
932 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
933 -----------------------------------------------------------------------------
944 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
946 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
947 tColorRGBA *sp, *csp, *dp;
951 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
952 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
954 /* allocate memory for row increments */
955 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
956 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
958 /* precalculate row increments */
961 for (x = 0; x <= dst->w; x++)
971 for (y = 0; y <= dst->h; y++)
980 sp = csp = (tColorRGBA *) src->pixels;
981 dp = (tColorRGBA *) dst->pixels;
982 sgap = src->pitch - src->w * 4;
983 dgap = dst->pitch - dst->w * 4;
986 for (y = 0; y < dst->h; y++)
991 for (x = 0; x < dst->w; x++)
996 /* advance source pointers */
1000 /* advance destination pointer */
1004 /* advance source pointer */
1006 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1008 /* advance destination pointers */
1009 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1019 -----------------------------------------------------------------------------
1022 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1023 -----------------------------------------------------------------------------
1026 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1028 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1029 Uint8 *sp, *dp, *csp;
1032 /* variable setup */
1033 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1034 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1036 /* allocate memory for row increments */
1037 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1038 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1040 /* precalculate row increments */
1043 for (x = 0; x < dst->w; x++)
1046 *csax = (csx >> 16);
1053 for (y = 0; y < dst->h; y++)
1056 *csay = (csy >> 16);
1063 for (x = 0; x < dst->w; x++)
1071 for (y = 0; y < dst->h; y++)
1078 sp = csp = (Uint8 *) src->pixels;
1079 dp = (Uint8 *) dst->pixels;
1080 dgap = dst->pitch - dst->w;
1084 for (y = 0; y < dst->h; y++)
1088 for (x = 0; x < dst->w; x++)
1093 /* advance source pointers */
1097 /* advance destination pointer */
1101 /* advance source pointer (for row) */
1102 csp += ((*csay) * src->pitch);
1105 /* advance destination pointers */
1116 -----------------------------------------------------------------------------
1119 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1120 'zoomx' and 'zoomy' are scaling factors for width and height.
1121 If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
1122 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1123 into a 32bit RGBA format on the fly.
1124 -----------------------------------------------------------------------------
1127 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1129 SDL_Surface *zoom_src = NULL;
1130 SDL_Surface *zoom_dst = NULL;
1131 boolean is_converted = FALSE;
1138 /* determine if source surface is 32 bit or 8 bit */
1139 is_32bit = (src->format->BitsPerPixel == 32);
1141 if (is_32bit || src->format->BitsPerPixel == 8)
1143 /* use source surface 'as is' */
1148 /* new source surface is 32 bit with a defined RGB ordering */
1149 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1150 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1151 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1153 is_converted = TRUE;
1156 /* allocate surface to completely contain the zoomed surface */
1159 /* target surface is 32 bit with source RGBA/ABGR ordering */
1160 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1161 zoom_src->format->Rmask,
1162 zoom_src->format->Gmask,
1163 zoom_src->format->Bmask, 0);
1167 /* target surface is 8 bit */
1168 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1172 /* lock source surface */
1173 SDL_LockSurface(zoom_src);
1175 /* check which kind of surface we have */
1178 /* call the 32 bit transformation routine to do the zooming */
1179 zoomSurfaceRGBA(zoom_src, zoom_dst);
1184 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1185 zoom_dst->format->palette->colors[i] =
1186 zoom_src->format->palette->colors[i];
1187 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1189 /* call the 8 bit transformation routine to do the zooming */
1190 zoomSurfaceY(zoom_src, zoom_dst);
1193 /* unlock source surface */
1194 SDL_UnlockSurface(zoom_src);
1196 /* free temporary surface */
1198 SDL_FreeSurface(zoom_src);
1200 /* return destination surface */
1204 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1206 SDL_Surface *sdl_surface_tmp;
1207 int dst_width = dst_bitmap->width;
1208 int dst_height = dst_bitmap->height;
1210 /* throw away old destination surface */
1211 SDL_FreeSurface(dst_bitmap->surface);
1213 /* create zoomed temporary surface from source surface */
1214 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1216 /* create native format destination surface from zoomed temporary surface */
1217 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1219 /* free temporary surface */
1220 SDL_FreeSurface(sdl_surface_tmp);
1224 /* ========================================================================= */
1225 /* load image to bitmap */
1226 /* ========================================================================= */
1228 Bitmap *SDLLoadImage(char *filename)
1230 Bitmap *new_bitmap = CreateBitmapStruct();
1231 SDL_Surface *sdl_image_tmp;
1233 /* load image to temporary surface */
1234 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1236 SetError("IMG_Load(): %s", SDL_GetError());
1240 /* create native non-transparent surface for current image */
1241 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1243 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1247 /* create native transparent surface for current image */
1248 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1249 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1250 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1252 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1256 /* free temporary surface */
1257 SDL_FreeSurface(sdl_image_tmp);
1259 new_bitmap->width = new_bitmap->surface->w;
1260 new_bitmap->height = new_bitmap->surface->h;
1266 /* ------------------------------------------------------------------------- */
1267 /* custom cursor fuctions */
1268 /* ------------------------------------------------------------------------- */
1270 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1272 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1273 cursor_info->width, cursor_info->height,
1274 cursor_info->hot_x, cursor_info->hot_y);
1277 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1279 static struct MouseCursorInfo *last_cursor_info = NULL;
1280 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1281 static SDL_Cursor *cursor_default = NULL;
1282 static SDL_Cursor *cursor_current = NULL;
1284 /* if invoked for the first time, store the SDL default cursor */
1285 if (cursor_default == NULL)
1286 cursor_default = SDL_GetCursor();
1288 /* only create new cursor if cursor info (custom only) has changed */
1289 if (cursor_info != NULL && cursor_info != last_cursor_info)
1291 cursor_current = create_cursor(cursor_info);
1292 last_cursor_info = cursor_info;
1295 /* only set new cursor if cursor info (custom or NULL) has changed */
1296 if (cursor_info != last_cursor_info2)
1297 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1299 last_cursor_info2 = cursor_info;
1303 /* ========================================================================= */
1304 /* audio functions */
1305 /* ========================================================================= */
1307 inline void SDLOpenAudio(void)
1309 if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
1310 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1312 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1314 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1318 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1319 AUDIO_NUM_CHANNELS_STEREO,
1320 setup.system.audio_fragment_size) < 0)
1322 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1326 audio.sound_available = TRUE;
1327 audio.music_available = TRUE;
1328 audio.loops_available = TRUE;
1329 audio.sound_enabled = TRUE;
1331 /* set number of available mixer channels */
1332 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1333 audio.music_channel = MUSIC_CHANNEL;
1334 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1336 Mixer_InitChannels();
1339 inline void SDLCloseAudio(void)
1342 Mix_HaltChannel(-1);
1345 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1349 /* ========================================================================= */
1350 /* event functions */
1351 /* ========================================================================= */
1353 inline void SDLNextEvent(Event *event)
1355 SDL_WaitEvent(event);
1357 #ifdef FULLSCREEN_BUG
1358 if (event->type == EVENT_BUTTONPRESS ||
1359 event->type == EVENT_BUTTONRELEASE)
1361 if (((ButtonEvent *)event)->x > video_xoffset)
1362 ((ButtonEvent *)event)->x -= video_xoffset;
1364 ((ButtonEvent *)event)->x = 0;
1365 if (((ButtonEvent *)event)->y > video_yoffset)
1366 ((ButtonEvent *)event)->y -= video_yoffset;
1368 ((ButtonEvent *)event)->y = 0;
1370 else if (event->type == EVENT_MOTIONNOTIFY)
1372 if (((MotionEvent *)event)->x > video_xoffset)
1373 ((MotionEvent *)event)->x -= video_xoffset;
1375 ((MotionEvent *)event)->x = 0;
1376 if (((MotionEvent *)event)->y > video_yoffset)
1377 ((MotionEvent *)event)->y -= video_yoffset;
1379 ((MotionEvent *)event)->y = 0;
1385 /* ========================================================================= */
1386 /* joystick functions */
1387 /* ========================================================================= */
1389 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1390 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1391 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1393 static boolean SDLOpenJoystick(int nr)
1395 if (nr < 0 || nr > MAX_PLAYERS)
1398 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1401 static void SDLCloseJoystick(int nr)
1403 if (nr < 0 || nr > MAX_PLAYERS)
1406 SDL_JoystickClose(sdl_joystick[nr]);
1409 static boolean SDLCheckJoystickOpened(int nr)
1411 if (nr < 0 || nr > MAX_PLAYERS)
1414 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1417 void HandleJoystickEvent(Event *event)
1421 case SDL_JOYAXISMOTION:
1422 if (event->jaxis.axis < 2)
1423 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1426 case SDL_JOYBUTTONDOWN:
1427 if (event->jbutton.button < 2)
1428 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1431 case SDL_JOYBUTTONUP:
1432 if (event->jbutton.button < 2)
1433 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1441 void SDLInitJoysticks()
1443 static boolean sdl_joystick_subsystem_initialized = FALSE;
1446 if (!sdl_joystick_subsystem_initialized)
1448 sdl_joystick_subsystem_initialized = TRUE;
1450 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1452 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1457 for (i = 0; i < MAX_PLAYERS; i++)
1459 char *device_name = setup.input[i].joy.device_name;
1460 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1462 if (joystick_nr >= SDL_NumJoysticks())
1465 /* misuse joystick file descriptor variable to store joystick number */
1466 joystick.fd[i] = joystick_nr;
1468 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1469 if (SDLCheckJoystickOpened(joystick_nr))
1470 SDLCloseJoystick(joystick_nr);
1472 if (!setup.input[i].use_joystick)
1475 if (!SDLOpenJoystick(joystick_nr))
1477 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1481 joystick.status = JOYSTICK_ACTIVATED;
1485 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1487 if (nr < 0 || nr >= MAX_PLAYERS)
1491 *x = sdl_js_axis[nr][0];
1493 *y = sdl_js_axis[nr][1];
1496 *b1 = sdl_js_button[nr][0];
1498 *b2 = sdl_js_button[nr][1];
1503 #endif /* TARGET_SDL */