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 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1120 'zoomx' and 'zoomy' are scaling factors for width and height.
1121 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1122 into a 32bit RGBA format on the fly.
1123 -----------------------------------------------------------------------------
1126 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1128 SDL_Surface *zoom_src = NULL;
1129 SDL_Surface *zoom_dst = NULL;
1130 boolean is_converted = FALSE;
1137 /* determine if source surface is 32 bit or 8 bit */
1138 is_32bit = (src->format->BitsPerPixel == 32);
1140 if (is_32bit || src->format->BitsPerPixel == 8)
1142 /* use source surface 'as is' */
1147 /* new source surface is 32 bit with a defined RGB ordering */
1148 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1149 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1150 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1152 is_converted = TRUE;
1155 /* allocate surface to completely contain the zoomed surface */
1158 /* target surface is 32 bit with source RGBA/ABGR ordering */
1159 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1160 zoom_src->format->Rmask,
1161 zoom_src->format->Gmask,
1162 zoom_src->format->Bmask, 0);
1166 /* target surface is 8 bit */
1167 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1171 /* lock source surface */
1172 SDL_LockSurface(zoom_src);
1174 /* check which kind of surface we have */
1177 /* call the 32 bit transformation routine to do the zooming */
1178 zoomSurfaceRGBA(zoom_src, zoom_dst);
1183 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1184 zoom_dst->format->palette->colors[i] =
1185 zoom_src->format->palette->colors[i];
1186 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1188 /* call the 8 bit transformation routine to do the zooming */
1189 zoomSurfaceY(zoom_src, zoom_dst);
1192 /* unlock source surface */
1193 SDL_UnlockSurface(zoom_src);
1195 /* free temporary surface */
1197 SDL_FreeSurface(zoom_src);
1199 /* return destination surface */
1203 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1205 SDL_Surface *sdl_surface_tmp;
1206 int dst_width = dst_bitmap->width;
1207 int dst_height = dst_bitmap->height;
1209 /* throw away old destination surface */
1210 SDL_FreeSurface(dst_bitmap->surface);
1212 /* create zoomed temporary surface from source surface */
1213 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1215 /* create native format destination surface from zoomed temporary surface */
1216 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1218 /* free temporary surface */
1219 SDL_FreeSurface(sdl_surface_tmp);
1223 /* ========================================================================= */
1224 /* load image to bitmap */
1225 /* ========================================================================= */
1227 Bitmap *SDLLoadImage(char *filename)
1229 Bitmap *new_bitmap = CreateBitmapStruct();
1230 SDL_Surface *sdl_image_tmp;
1232 /* load image to temporary surface */
1233 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1235 SetError("IMG_Load(): %s", SDL_GetError());
1239 /* create native non-transparent surface for current image */
1240 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1242 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1246 /* create native transparent surface for current image */
1247 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1248 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1249 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1251 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1255 /* free temporary surface */
1256 SDL_FreeSurface(sdl_image_tmp);
1258 new_bitmap->width = new_bitmap->surface->w;
1259 new_bitmap->height = new_bitmap->surface->h;
1265 /* ------------------------------------------------------------------------- */
1266 /* custom cursor fuctions */
1267 /* ------------------------------------------------------------------------- */
1269 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1271 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1272 cursor_info->width, cursor_info->height,
1273 cursor_info->hot_x, cursor_info->hot_y);
1276 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1278 static struct MouseCursorInfo *last_cursor_info = NULL;
1279 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1280 static SDL_Cursor *cursor_default = NULL;
1281 static SDL_Cursor *cursor_current = NULL;
1283 /* if invoked for the first time, store the SDL default cursor */
1284 if (cursor_default == NULL)
1285 cursor_default = SDL_GetCursor();
1287 /* only create new cursor if cursor info (custom only) has changed */
1288 if (cursor_info != NULL && cursor_info != last_cursor_info)
1290 cursor_current = create_cursor(cursor_info);
1291 last_cursor_info = cursor_info;
1294 /* only set new cursor if cursor info (custom or NULL) has changed */
1295 if (cursor_info != last_cursor_info2)
1296 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1298 last_cursor_info2 = cursor_info;
1302 /* ========================================================================= */
1303 /* audio functions */
1304 /* ========================================================================= */
1306 inline void SDLOpenAudio(void)
1308 if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
1309 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1311 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1313 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1317 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1318 AUDIO_NUM_CHANNELS_STEREO,
1319 setup.system.audio_fragment_size) < 0)
1321 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1325 audio.sound_available = TRUE;
1326 audio.music_available = TRUE;
1327 audio.loops_available = TRUE;
1328 audio.sound_enabled = TRUE;
1330 /* set number of available mixer channels */
1331 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1332 audio.music_channel = MUSIC_CHANNEL;
1333 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1335 Mixer_InitChannels();
1338 inline void SDLCloseAudio(void)
1341 Mix_HaltChannel(-1);
1344 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1348 /* ========================================================================= */
1349 /* event functions */
1350 /* ========================================================================= */
1352 inline void SDLNextEvent(Event *event)
1354 SDL_WaitEvent(event);
1356 #ifdef FULLSCREEN_BUG
1357 if (event->type == EVENT_BUTTONPRESS ||
1358 event->type == EVENT_BUTTONRELEASE)
1360 if (((ButtonEvent *)event)->x > video_xoffset)
1361 ((ButtonEvent *)event)->x -= video_xoffset;
1363 ((ButtonEvent *)event)->x = 0;
1364 if (((ButtonEvent *)event)->y > video_yoffset)
1365 ((ButtonEvent *)event)->y -= video_yoffset;
1367 ((ButtonEvent *)event)->y = 0;
1369 else if (event->type == EVENT_MOTIONNOTIFY)
1371 if (((MotionEvent *)event)->x > video_xoffset)
1372 ((MotionEvent *)event)->x -= video_xoffset;
1374 ((MotionEvent *)event)->x = 0;
1375 if (((MotionEvent *)event)->y > video_yoffset)
1376 ((MotionEvent *)event)->y -= video_yoffset;
1378 ((MotionEvent *)event)->y = 0;
1384 /* ========================================================================= */
1385 /* joystick functions */
1386 /* ========================================================================= */
1388 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1389 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1390 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1392 static boolean SDLOpenJoystick(int nr)
1394 if (nr < 0 || nr > MAX_PLAYERS)
1397 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1400 static void SDLCloseJoystick(int nr)
1402 if (nr < 0 || nr > MAX_PLAYERS)
1405 SDL_JoystickClose(sdl_joystick[nr]);
1408 static boolean SDLCheckJoystickOpened(int nr)
1410 if (nr < 0 || nr > MAX_PLAYERS)
1413 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1416 void HandleJoystickEvent(Event *event)
1420 case SDL_JOYAXISMOTION:
1421 if (event->jaxis.axis < 2)
1422 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1425 case SDL_JOYBUTTONDOWN:
1426 if (event->jbutton.button < 2)
1427 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1430 case SDL_JOYBUTTONUP:
1431 if (event->jbutton.button < 2)
1432 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1440 void SDLInitJoysticks()
1442 static boolean sdl_joystick_subsystem_initialized = FALSE;
1445 if (!sdl_joystick_subsystem_initialized)
1447 sdl_joystick_subsystem_initialized = TRUE;
1449 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1451 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1456 for (i = 0; i < MAX_PLAYERS; i++)
1458 char *device_name = setup.input[i].joy.device_name;
1459 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1461 if (joystick_nr >= SDL_NumJoysticks())
1464 /* misuse joystick file descriptor variable to store joystick number */
1465 joystick.fd[i] = joystick_nr;
1467 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1468 if (SDLCheckJoystickOpened(joystick_nr))
1469 SDLCloseJoystick(joystick_nr);
1471 if (!setup.input[i].use_joystick)
1474 if (!SDLOpenJoystick(joystick_nr))
1476 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1480 joystick.status = JOYSTICK_ACTIVATED;
1484 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1486 if (nr < 0 || nr >= MAX_PLAYERS)
1490 *x = sdl_js_axis[nr][0];
1492 *y = sdl_js_axis[nr][1];
1495 *b1 = sdl_js_button[nr][0];
1497 *b2 = sdl_js_button[nr][1];
1502 #endif /* TARGET_SDL */