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 SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
176 int src_x, int src_y,
177 int width, int height,
178 int dst_x, int dst_y, int mask_mode)
180 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
181 SDL_Rect src_rect, dst_rect;
183 #ifdef FULLSCREEN_BUG
184 if (src_bitmap == backbuffer)
186 src_x += video_xoffset;
187 src_y += video_yoffset;
196 #ifdef FULLSCREEN_BUG
197 if (dst_bitmap == backbuffer || dst_bitmap == window)
199 dst_x += video_xoffset;
200 dst_y += video_yoffset;
209 if (src_bitmap != backbuffer || dst_bitmap != window)
210 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
211 src_bitmap->surface_masked : src_bitmap->surface),
212 &src_rect, real_dst_bitmap->surface, &dst_rect);
214 if (dst_bitmap == window)
215 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
218 inline void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
219 int width, int height, Uint32 color)
221 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
224 unsigned int color_r = (color >> 16) & 0xff;
225 unsigned int color_g = (color >> 8) & 0xff;
226 unsigned int color_b = (color >> 0) & 0xff;
229 #ifdef FULLSCREEN_BUG
230 if (dst_bitmap == backbuffer || dst_bitmap == window)
243 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
245 SDL_FillRect(real_dst_bitmap->surface, &rect,
246 SDL_MapRGB(real_dst_bitmap->surface->format,
247 color_r, color_g, color_b));
250 if (dst_bitmap == window)
251 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
254 inline void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
255 int to_x, int to_y, Uint32 color)
257 SDL_Surface *surface = dst_bitmap->surface;
260 unsigned int color_r = (color >> 16) & 0xff;
261 unsigned int color_g = (color >> 8) & 0xff;
262 unsigned int color_b = (color >> 0) & 0xff;
266 swap_numbers(&from_x, &to_x);
269 swap_numbers(&from_y, &to_y);
273 rect.w = (to_x - from_x + 1);
274 rect.h = (to_y - from_y + 1);
276 #ifdef FULLSCREEN_BUG
277 if (dst_bitmap == backbuffer || dst_bitmap == window)
279 rect.x += video_xoffset;
280 rect.y += video_yoffset;
285 SDL_FillRect(surface, &rect, color);
287 SDL_FillRect(surface, &rect,
288 SDL_MapRGB(surface->format, color_r, color_g, color_b));
292 inline void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
293 int to_x, int to_y, Uint32 color)
295 #ifdef FULLSCREEN_BUG
296 if (dst_bitmap == backbuffer || dst_bitmap == window)
298 from_x += video_xoffset;
299 from_y += video_yoffset;
300 to_x += video_xoffset;
301 to_y += video_yoffset;
305 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
309 inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
310 int num_points, Uint32 color)
315 for (i=0; i<num_points - 1; i++)
317 for (x=0; x<line_width; x++)
319 for (y=0; y<line_width; y++)
321 int dx = x - line_width / 2;
322 int dy = y - line_width / 2;
324 if ((x == 0 && y == 0) ||
325 (x == 0 && y == line_width - 1) ||
326 (x == line_width - 1 && y == 0) ||
327 (x == line_width - 1 && y == line_width - 1))
330 sge_Line(surface, points[i].x + dx, points[i].y + dy,
331 points[i+1].x + dx, points[i+1].y + dy, color);
338 inline Pixel SDLGetPixel(Bitmap *dst_bitmap, int x, int y)
340 SDL_Surface *surface = dst_bitmap->surface;
342 #ifdef FULLSCREEN_BUG
343 if (dst_bitmap == backbuffer || dst_bitmap == window)
350 switch (surface->format->BytesPerPixel)
352 case 1: /* assuming 8-bpp */
354 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
358 case 2: /* probably 15-bpp or 16-bpp */
360 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
364 case 3: /* slow 24-bpp mode; usually not used */
366 /* does this work? */
367 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
371 shift = surface->format->Rshift;
372 color |= *(pix + shift / 8) >> shift;
373 shift = surface->format->Gshift;
374 color |= *(pix + shift / 8) >> shift;
375 shift = surface->format->Bshift;
376 color |= *(pix + shift / 8) >> shift;
382 case 4: /* probably 32-bpp */
384 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
393 /* ========================================================================= */
394 /* The following functions were taken from the SGE library */
395 /* (SDL Graphics Extension Library) by Anders Lindström */
396 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
397 /* ========================================================================= */
399 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
401 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
403 switch (surface->format->BytesPerPixel)
408 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
414 /* Probably 15-bpp or 16-bpp */
415 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
421 /* Slow 24-bpp mode, usually not used */
425 /* Gack - slow, but endian correct */
426 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
427 shift = surface->format->Rshift;
428 *(pix+shift/8) = color>>shift;
429 shift = surface->format->Gshift;
430 *(pix+shift/8) = color>>shift;
431 shift = surface->format->Bshift;
432 *(pix+shift/8) = color>>shift;
438 /* Probably 32-bpp */
439 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
446 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
447 Uint8 R, Uint8 G, Uint8 B)
449 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
452 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
454 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
457 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
459 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
462 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
467 /* Gack - slow, but endian correct */
468 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
469 shift = surface->format->Rshift;
470 *(pix+shift/8) = color>>shift;
471 shift = surface->format->Gshift;
472 *(pix+shift/8) = color>>shift;
473 shift = surface->format->Bshift;
474 *(pix+shift/8) = color>>shift;
477 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
479 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
482 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
484 switch (dest->format->BytesPerPixel)
487 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
491 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
495 _PutPixel24(dest,x,y,color);
499 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
504 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
506 if (SDL_MUSTLOCK(surface))
508 if (SDL_LockSurface(surface) < 0)
514 _PutPixel(surface, x, y, color);
516 if (SDL_MUSTLOCK(surface))
518 SDL_UnlockSurface(surface);
522 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
523 Uint8 R, Uint8 G, Uint8 B)
525 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
528 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
530 if (y >= 0 && y <= dest->h - 1)
532 switch (dest->format->BytesPerPixel)
535 return y*dest->pitch;
539 return y*dest->pitch/2;
543 return y*dest->pitch;
547 return y*dest->pitch/4;
555 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
557 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
559 switch (surface->format->BytesPerPixel)
564 *((Uint8 *)surface->pixels + ypitch + x) = color;
570 /* Probably 15-bpp or 16-bpp */
571 *((Uint16 *)surface->pixels + ypitch + x) = color;
577 /* Slow 24-bpp mode, usually not used */
581 /* Gack - slow, but endian correct */
582 pix = (Uint8 *)surface->pixels + ypitch + x*3;
583 shift = surface->format->Rshift;
584 *(pix+shift/8) = color>>shift;
585 shift = surface->format->Gshift;
586 *(pix+shift/8) = color>>shift;
587 shift = surface->format->Bshift;
588 *(pix+shift/8) = color>>shift;
594 /* Probably 32-bpp */
595 *((Uint32 *)surface->pixels + ypitch + x) = color;
602 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
607 if (SDL_MUSTLOCK(Surface))
609 if (SDL_LockSurface(Surface) < 0)
622 /* Do the clipping */
623 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
627 if (x2 > Surface->w - 1)
635 SDL_FillRect(Surface, &l, Color);
637 if (SDL_MUSTLOCK(Surface))
639 SDL_UnlockSurface(Surface);
643 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
644 Uint8 R, Uint8 G, Uint8 B)
646 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
649 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
660 /* Do the clipping */
661 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
665 if (x2 > Surface->w - 1)
673 SDL_FillRect(Surface, &l, Color);
676 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
681 if (SDL_MUSTLOCK(Surface))
683 if (SDL_LockSurface(Surface) < 0)
696 /* Do the clipping */
697 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
701 if (y2 > Surface->h - 1)
709 SDL_FillRect(Surface, &l, Color);
711 if (SDL_MUSTLOCK(Surface))
713 SDL_UnlockSurface(Surface);
717 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
718 Uint8 R, Uint8 G, Uint8 B)
720 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
723 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
734 /* Do the clipping */
735 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
739 if (y2 > Surface->h - 1)
747 SDL_FillRect(Surface, &l, Color);
750 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
751 Sint16 x2, Sint16 y2, Uint32 Color,
752 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
755 Sint16 dx, dy, sdx, sdy, x, y, px, py;
760 sdx = (dx < 0) ? -1 : 1;
761 sdy = (dy < 0) ? -1 : 1;
773 for (x = 0; x < dx; x++)
775 Callback(Surface, px, py, Color);
789 for (y = 0; y < dy; y++)
791 Callback(Surface, px, py, Color);
805 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
806 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
807 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
810 sge_DoLine(Surface, X1, Y1, X2, Y2,
811 SDL_MapRGB(Surface->format, R, G, B), Callback);
814 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
817 if (SDL_MUSTLOCK(Surface))
819 if (SDL_LockSurface(Surface) < 0)
824 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
826 /* unlock the display */
827 if (SDL_MUSTLOCK(Surface))
829 SDL_UnlockSurface(Surface);
833 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
834 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
836 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
840 /* ========================================================================= */
841 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
842 /* (Rotozoomer) by Andreas Schiffler */
843 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
844 /* ========================================================================= */
847 -----------------------------------------------------------------------------
850 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
851 -----------------------------------------------------------------------------
862 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
864 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
865 tColorRGBA *sp, *csp, *dp;
869 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
870 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
872 /* allocate memory for row increments */
873 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
874 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
876 /* precalculate row increments */
879 for (x = 0; x <= dst->w; x++)
889 for (y = 0; y <= dst->h; y++)
898 sp = csp = (tColorRGBA *) src->pixels;
899 dp = (tColorRGBA *) dst->pixels;
900 sgap = src->pitch - src->w * 4;
901 dgap = dst->pitch - dst->w * 4;
904 for (y = 0; y < dst->h; y++)
909 for (x = 0; x < dst->w; x++)
914 /* advance source pointers */
918 /* advance destination pointer */
922 /* advance source pointer */
924 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
926 /* advance destination pointers */
927 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
937 -----------------------------------------------------------------------------
940 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
941 -----------------------------------------------------------------------------
944 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
946 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
947 Uint8 *sp, *dp, *csp;
951 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
952 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
954 /* allocate memory for row increments */
955 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
956 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
958 /* precalculate row increments */
961 for (x = 0; x < dst->w; x++)
971 for (y = 0; y < dst->h; y++)
981 for (x = 0; x < dst->w; x++)
989 for (y = 0; y < dst->h; y++)
996 sp = csp = (Uint8 *) src->pixels;
997 dp = (Uint8 *) dst->pixels;
998 dgap = dst->pitch - dst->w;
1002 for (y = 0; y < dst->h; y++)
1006 for (x = 0; x < dst->w; x++)
1011 /* advance source pointers */
1015 /* advance destination pointer */
1019 /* advance source pointer (for row) */
1020 csp += ((*csay) * src->pitch);
1023 /* advance destination pointers */
1034 -----------------------------------------------------------------------------
1037 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1038 'zoomx' and 'zoomy' are scaling factors for width and height.
1039 If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
1040 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1041 into a 32bit RGBA format on the fly.
1042 -----------------------------------------------------------------------------
1045 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1047 SDL_Surface *zoom_src = NULL;
1048 SDL_Surface *zoom_dst = NULL;
1049 boolean is_converted = FALSE;
1056 /* determine if source surface is 32 bit or 8 bit */
1057 is_32bit = (src->format->BitsPerPixel == 32);
1059 if (is_32bit || src->format->BitsPerPixel == 8)
1061 /* use source surface 'as is' */
1066 /* new source surface is 32 bit with a defined RGB ordering */
1067 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1068 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1069 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1071 is_converted = TRUE;
1074 /* allocate surface to completely contain the zoomed surface */
1077 /* target surface is 32 bit with source RGBA/ABGR ordering */
1078 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1079 zoom_src->format->Rmask,
1080 zoom_src->format->Gmask,
1081 zoom_src->format->Bmask, 0);
1085 /* target surface is 8 bit */
1086 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1090 /* lock source surface */
1091 SDL_LockSurface(zoom_src);
1093 /* check which kind of surface we have */
1096 /* call the 32 bit transformation routine to do the zooming */
1097 zoomSurfaceRGBA(zoom_src, zoom_dst);
1102 for (i=0; i < zoom_src->format->palette->ncolors; i++)
1103 zoom_dst->format->palette->colors[i] =
1104 zoom_src->format->palette->colors[i];
1105 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1107 /* call the 8 bit transformation routine to do the zooming */
1108 zoomSurfaceY(zoom_src, zoom_dst);
1111 /* unlock source surface */
1112 SDL_UnlockSurface(zoom_src);
1114 /* free temporary surface */
1116 SDL_FreeSurface(zoom_src);
1118 /* return destination surface */
1122 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1124 SDL_Surface *sdl_surface_tmp;
1125 int dst_width = dst_bitmap->width;
1126 int dst_height = dst_bitmap->height;
1128 /* throw away old destination surface */
1129 SDL_FreeSurface(dst_bitmap->surface);
1131 /* create zoomed temporary surface from source surface */
1132 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1134 /* create native format destination surface from zoomed temporary surface */
1135 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1137 /* free temporary surface */
1138 SDL_FreeSurface(sdl_surface_tmp);
1142 /* ========================================================================= */
1143 /* load image to bitmap */
1144 /* ========================================================================= */
1146 Bitmap *SDLLoadImage(char *filename)
1148 Bitmap *new_bitmap = CreateBitmapStruct();
1149 SDL_Surface *sdl_image_tmp;
1151 /* load image to temporary surface */
1152 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1154 SetError("IMG_Load(): %s", SDL_GetError());
1158 /* create native non-transparent surface for current image */
1159 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1161 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1165 /* create native transparent surface for current image */
1166 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1167 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1168 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1170 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1174 /* free temporary surface */
1175 SDL_FreeSurface(sdl_image_tmp);
1177 new_bitmap->width = new_bitmap->surface->w;
1178 new_bitmap->height = new_bitmap->surface->h;
1184 /* ========================================================================= */
1185 /* audio functions */
1186 /* ========================================================================= */
1188 inline void SDLOpenAudio(void)
1190 if (strcmp(setup.system.sdl_audiodriver, ARG_DEFAULT) != 0)
1191 putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1193 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1195 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1199 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1200 AUDIO_NUM_CHANNELS_STEREO,
1201 setup.system.audio_fragment_size) < 0)
1203 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1207 audio.sound_available = TRUE;
1208 audio.music_available = TRUE;
1209 audio.loops_available = TRUE;
1210 audio.sound_enabled = TRUE;
1212 /* set number of available mixer channels */
1213 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1214 audio.music_channel = MUSIC_CHANNEL;
1215 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1217 Mixer_InitChannels();
1220 inline void SDLCloseAudio(void)
1223 Mix_HaltChannel(-1);
1226 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1230 /* ========================================================================= */
1231 /* event functions */
1232 /* ========================================================================= */
1234 inline void SDLNextEvent(Event *event)
1236 SDL_WaitEvent(event);
1238 #ifdef FULLSCREEN_BUG
1239 if (event->type == EVENT_BUTTONPRESS ||
1240 event->type == EVENT_BUTTONRELEASE)
1242 if (((ButtonEvent *)event)->x > video_xoffset)
1243 ((ButtonEvent *)event)->x -= video_xoffset;
1245 ((ButtonEvent *)event)->x = 0;
1246 if (((ButtonEvent *)event)->y > video_yoffset)
1247 ((ButtonEvent *)event)->y -= video_yoffset;
1249 ((ButtonEvent *)event)->y = 0;
1251 else if (event->type == EVENT_MOTIONNOTIFY)
1253 if (((ButtonEvent *)event)->x > video_xoffset)
1254 ((ButtonEvent *)event)->x -= video_xoffset;
1256 ((ButtonEvent *)event)->x = 0;
1257 if (((ButtonEvent *)event)->y > video_yoffset)
1258 ((ButtonEvent *)event)->y -= video_yoffset;
1260 ((ButtonEvent *)event)->y = 0;
1266 /* ========================================================================= */
1267 /* joystick functions */
1268 /* ========================================================================= */
1270 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1271 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1272 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1274 static boolean SDLOpenJoystick(int nr)
1276 if (nr < 0 || nr > MAX_PLAYERS)
1279 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1282 static void SDLCloseJoystick(int nr)
1284 if (nr < 0 || nr > MAX_PLAYERS)
1287 SDL_JoystickClose(sdl_joystick[nr]);
1290 static boolean SDLCheckJoystickOpened(int nr)
1292 if (nr < 0 || nr > MAX_PLAYERS)
1295 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1298 void HandleJoystickEvent(Event *event)
1302 case SDL_JOYAXISMOTION:
1303 if (event->jaxis.axis < 2)
1304 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1307 case SDL_JOYBUTTONDOWN:
1308 if (event->jbutton.button < 2)
1309 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1312 case SDL_JOYBUTTONUP:
1313 if (event->jbutton.button < 2)
1314 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1322 void SDLInitJoysticks()
1324 static boolean sdl_joystick_subsystem_initialized = FALSE;
1327 if (!sdl_joystick_subsystem_initialized)
1329 sdl_joystick_subsystem_initialized = TRUE;
1331 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1333 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1338 for (i=0; i<MAX_PLAYERS; i++)
1340 char *device_name = setup.input[i].joy.device_name;
1341 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1343 if (joystick_nr >= SDL_NumJoysticks())
1346 /* misuse joystick file descriptor variable to store joystick number */
1347 joystick.fd[i] = joystick_nr;
1349 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1350 if (SDLCheckJoystickOpened(joystick_nr))
1351 SDLCloseJoystick(joystick_nr);
1353 if (!setup.input[i].use_joystick)
1356 if (!SDLOpenJoystick(joystick_nr))
1358 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1362 joystick.status = JOYSTICK_ACTIVATED;
1366 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1368 if (nr < 0 || nr >= MAX_PLAYERS)
1372 *x = sdl_js_axis[nr][0];
1374 *y = sdl_js_axis[nr][1];
1377 *b1 = sdl_js_button[nr][0];
1379 *b2 = sdl_js_button[nr][1];
1384 #endif /* TARGET_SDL */