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 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 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
874 -----------------------------------------------------------------------------
875 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
876 -----------------------------------------------------------------------------
879 inline void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
880 int width, int height, Uint32 color)
884 for (y=src_y; y < src_y + height; y++)
886 for (x=src_x; x < src_x + width; x++)
888 Uint32 pixel = SDLGetPixel(bitmap, x, y);
890 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
895 inline void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
896 int src_x, int src_y, int width, int height,
897 int dst_x, int dst_y)
901 for (y=0; y < height; y++)
903 for (x=0; x < width; x++)
905 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
907 if (pixel != BLACK_PIXEL)
908 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
914 /* ========================================================================= */
915 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
916 /* (Rotozoomer) by Andreas Schiffler */
917 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
918 /* ========================================================================= */
921 -----------------------------------------------------------------------------
924 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
925 -----------------------------------------------------------------------------
936 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
938 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
939 tColorRGBA *sp, *csp, *dp;
943 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
944 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
946 /* allocate memory for row increments */
947 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
948 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
950 /* precalculate row increments */
953 for (x = 0; x <= dst->w; x++)
963 for (y = 0; y <= dst->h; y++)
972 sp = csp = (tColorRGBA *) src->pixels;
973 dp = (tColorRGBA *) dst->pixels;
974 sgap = src->pitch - src->w * 4;
975 dgap = dst->pitch - dst->w * 4;
978 for (y = 0; y < dst->h; y++)
983 for (x = 0; x < dst->w; x++)
988 /* advance source pointers */
992 /* advance destination pointer */
996 /* advance source pointer */
998 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1000 /* advance destination pointers */
1001 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1011 -----------------------------------------------------------------------------
1014 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1015 -----------------------------------------------------------------------------
1018 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1020 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1021 Uint8 *sp, *dp, *csp;
1024 /* variable setup */
1025 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1026 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1028 /* allocate memory for row increments */
1029 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1030 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1032 /* precalculate row increments */
1035 for (x = 0; x < dst->w; x++)
1038 *csax = (csx >> 16);
1045 for (y = 0; y < dst->h; y++)
1048 *csay = (csy >> 16);
1055 for (x = 0; x < dst->w; x++)
1063 for (y = 0; y < dst->h; y++)
1070 sp = csp = (Uint8 *) src->pixels;
1071 dp = (Uint8 *) dst->pixels;
1072 dgap = dst->pitch - dst->w;
1076 for (y = 0; y < dst->h; y++)
1080 for (x = 0; x < dst->w; x++)
1085 /* advance source pointers */
1089 /* advance destination pointer */
1093 /* advance source pointer (for row) */
1094 csp += ((*csay) * src->pitch);
1097 /* advance destination pointers */
1108 -----------------------------------------------------------------------------
1111 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1112 'zoomx' and 'zoomy' are scaling factors for width and height.
1113 If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
1114 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1115 into a 32bit RGBA format on the fly.
1116 -----------------------------------------------------------------------------
1119 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1121 SDL_Surface *zoom_src = NULL;
1122 SDL_Surface *zoom_dst = NULL;
1123 boolean is_converted = FALSE;
1130 /* determine if source surface is 32 bit or 8 bit */
1131 is_32bit = (src->format->BitsPerPixel == 32);
1133 if (is_32bit || src->format->BitsPerPixel == 8)
1135 /* use source surface 'as is' */
1140 /* new source surface is 32 bit with a defined RGB ordering */
1141 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1142 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1143 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1145 is_converted = TRUE;
1148 /* allocate surface to completely contain the zoomed surface */
1151 /* target surface is 32 bit with source RGBA/ABGR ordering */
1152 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1153 zoom_src->format->Rmask,
1154 zoom_src->format->Gmask,
1155 zoom_src->format->Bmask, 0);
1159 /* target surface is 8 bit */
1160 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1164 /* lock source surface */
1165 SDL_LockSurface(zoom_src);
1167 /* check which kind of surface we have */
1170 /* call the 32 bit transformation routine to do the zooming */
1171 zoomSurfaceRGBA(zoom_src, zoom_dst);
1176 for (i=0; i < zoom_src->format->palette->ncolors; i++)
1177 zoom_dst->format->palette->colors[i] =
1178 zoom_src->format->palette->colors[i];
1179 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1181 /* call the 8 bit transformation routine to do the zooming */
1182 zoomSurfaceY(zoom_src, zoom_dst);
1185 /* unlock source surface */
1186 SDL_UnlockSurface(zoom_src);
1188 /* free temporary surface */
1190 SDL_FreeSurface(zoom_src);
1192 /* return destination surface */
1196 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1198 SDL_Surface *sdl_surface_tmp;
1199 int dst_width = dst_bitmap->width;
1200 int dst_height = dst_bitmap->height;
1202 /* throw away old destination surface */
1203 SDL_FreeSurface(dst_bitmap->surface);
1205 /* create zoomed temporary surface from source surface */
1206 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1208 /* create native format destination surface from zoomed temporary surface */
1209 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1211 /* free temporary surface */
1212 SDL_FreeSurface(sdl_surface_tmp);
1216 /* ========================================================================= */
1217 /* load image to bitmap */
1218 /* ========================================================================= */
1220 Bitmap *SDLLoadImage(char *filename)
1222 Bitmap *new_bitmap = CreateBitmapStruct();
1223 SDL_Surface *sdl_image_tmp;
1225 /* load image to temporary surface */
1226 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1228 SetError("IMG_Load(): %s", SDL_GetError());
1232 /* create native non-transparent surface for current image */
1233 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1235 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1239 /* create native transparent surface for current image */
1240 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1241 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1242 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1244 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1248 /* free temporary surface */
1249 SDL_FreeSurface(sdl_image_tmp);
1251 new_bitmap->width = new_bitmap->surface->w;
1252 new_bitmap->height = new_bitmap->surface->h;
1258 /* ------------------------------------------------------------------------- */
1259 /* custom cursor fuctions */
1260 /* ------------------------------------------------------------------------- */
1262 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1264 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1265 cursor_info->width, cursor_info->height,
1266 cursor_info->hot_x, cursor_info->hot_y);
1269 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1271 static struct MouseCursorInfo *last_cursor_info = NULL;
1272 static SDL_Cursor *cursor_default = NULL;
1273 static SDL_Cursor *cursor_current = NULL;
1275 if (cursor_default == NULL)
1276 cursor_default = SDL_GetCursor();
1278 if (cursor_info != NULL && cursor_info != last_cursor_info)
1280 cursor_current = create_cursor(cursor_info);
1281 last_cursor_info = cursor_info;
1284 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1288 /* ========================================================================= */
1289 /* audio functions */
1290 /* ========================================================================= */
1292 inline void SDLOpenAudio(void)
1294 if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
1295 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1297 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1299 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1303 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1304 AUDIO_NUM_CHANNELS_STEREO,
1305 setup.system.audio_fragment_size) < 0)
1307 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1311 audio.sound_available = TRUE;
1312 audio.music_available = TRUE;
1313 audio.loops_available = TRUE;
1314 audio.sound_enabled = TRUE;
1316 /* set number of available mixer channels */
1317 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1318 audio.music_channel = MUSIC_CHANNEL;
1319 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1321 Mixer_InitChannels();
1324 inline void SDLCloseAudio(void)
1327 Mix_HaltChannel(-1);
1330 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1334 /* ========================================================================= */
1335 /* event functions */
1336 /* ========================================================================= */
1338 inline void SDLNextEvent(Event *event)
1340 SDL_WaitEvent(event);
1342 #ifdef FULLSCREEN_BUG
1343 if (event->type == EVENT_BUTTONPRESS ||
1344 event->type == EVENT_BUTTONRELEASE)
1346 if (((ButtonEvent *)event)->x > video_xoffset)
1347 ((ButtonEvent *)event)->x -= video_xoffset;
1349 ((ButtonEvent *)event)->x = 0;
1350 if (((ButtonEvent *)event)->y > video_yoffset)
1351 ((ButtonEvent *)event)->y -= video_yoffset;
1353 ((ButtonEvent *)event)->y = 0;
1355 else if (event->type == EVENT_MOTIONNOTIFY)
1357 if (((MotionEvent *)event)->x > video_xoffset)
1358 ((MotionEvent *)event)->x -= video_xoffset;
1360 ((MotionEvent *)event)->x = 0;
1361 if (((MotionEvent *)event)->y > video_yoffset)
1362 ((MotionEvent *)event)->y -= video_yoffset;
1364 ((MotionEvent *)event)->y = 0;
1370 /* ========================================================================= */
1371 /* joystick functions */
1372 /* ========================================================================= */
1374 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1375 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1376 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1378 static boolean SDLOpenJoystick(int nr)
1380 if (nr < 0 || nr > MAX_PLAYERS)
1383 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1386 static void SDLCloseJoystick(int nr)
1388 if (nr < 0 || nr > MAX_PLAYERS)
1391 SDL_JoystickClose(sdl_joystick[nr]);
1394 static boolean SDLCheckJoystickOpened(int nr)
1396 if (nr < 0 || nr > MAX_PLAYERS)
1399 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1402 void HandleJoystickEvent(Event *event)
1406 case SDL_JOYAXISMOTION:
1407 if (event->jaxis.axis < 2)
1408 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1411 case SDL_JOYBUTTONDOWN:
1412 if (event->jbutton.button < 2)
1413 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1416 case SDL_JOYBUTTONUP:
1417 if (event->jbutton.button < 2)
1418 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1426 void SDLInitJoysticks()
1428 static boolean sdl_joystick_subsystem_initialized = FALSE;
1431 if (!sdl_joystick_subsystem_initialized)
1433 sdl_joystick_subsystem_initialized = TRUE;
1435 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1437 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1442 for (i=0; i<MAX_PLAYERS; i++)
1444 char *device_name = setup.input[i].joy.device_name;
1445 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1447 if (joystick_nr >= SDL_NumJoysticks())
1450 /* misuse joystick file descriptor variable to store joystick number */
1451 joystick.fd[i] = joystick_nr;
1453 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1454 if (SDLCheckJoystickOpened(joystick_nr))
1455 SDLCloseJoystick(joystick_nr);
1457 if (!setup.input[i].use_joystick)
1460 if (!SDLOpenJoystick(joystick_nr))
1462 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1466 joystick.status = JOYSTICK_ACTIVATED;
1470 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1472 if (nr < 0 || nr >= MAX_PLAYERS)
1476 *x = sdl_js_axis[nr][0];
1478 *y = sdl_js_axis[nr][1];
1481 *b1 = sdl_js_button[nr][0];
1483 *b2 = sdl_js_button[nr][1];
1488 #endif /* TARGET_SDL */