1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
19 #if defined(PLATFORM_MSDOS)
31 /* ========================================================================= */
32 /* exported variables */
33 /* ========================================================================= */
35 struct ProgramInfo program;
36 struct OptionInfo options;
37 struct VideoSystemInfo video;
38 struct AudioSystemInfo audio;
40 struct ArtworkInfo artwork;
41 struct JoystickInfo joystick;
42 struct SetupInfo setup;
44 LevelDirTree *leveldir_first_all = NULL;
45 LevelDirTree *leveldir_first = NULL;
46 LevelDirTree *leveldir_current = NULL;
49 Display *display = NULL;
50 Visual *visual = NULL;
54 DrawWindow *window = NULL;
55 DrawBuffer *backbuffer = NULL;
56 DrawBuffer *drawto = NULL;
58 int button_status = MB_NOT_PRESSED;
59 boolean motion_status = FALSE;
61 int redraw_mask = REDRAW_NONE;
67 /* ========================================================================= */
68 /* init/close functions */
69 /* ========================================================================= */
71 void InitProgramInfo(char *argv0,
72 char *userdata_subdir, char *userdata_subdir_unix,
73 char *program_title, char *window_title, char *icon_title,
74 char *x11_icon_filename, char *x11_iconmask_filename,
75 char *sdl_icon_filename, char *msdos_cursor_filename,
76 char *cookie_prefix, char *filename_prefix,
79 program.command_basepath = getBasePath(argv0);
80 program.command_basename = getBaseName(argv0);
82 program.userdata_subdir = userdata_subdir;
83 program.userdata_subdir_unix = userdata_subdir_unix;
84 program.userdata_path = getUserGameDataDir();
86 program.program_title = program_title;
87 program.window_title = window_title;
88 program.icon_title = icon_title;
90 program.x11_icon_filename = x11_icon_filename;
91 program.x11_iconmask_filename = x11_iconmask_filename;
92 program.sdl_icon_filename = sdl_icon_filename;
93 program.msdos_cursor_filename = msdos_cursor_filename;
95 program.cookie_prefix = cookie_prefix;
96 program.filename_prefix = filename_prefix;
98 program.version_major = VERSION_MAJOR(program_version);
99 program.version_minor = VERSION_MINOR(program_version);
100 program.version_patch = VERSION_PATCH(program_version);
102 program.error_filename = getErrorFilename(ERROR_BASENAME);
103 program.error_file = stderr;
106 void InitExitFunction(void (*exit_function)(int))
108 program.exit_function = exit_function;
110 /* set signal handlers to custom exit function */
111 signal(SIGINT, exit_function);
112 signal(SIGTERM, exit_function);
114 #if defined(TARGET_SDL)
115 /* set exit function to automatically cleanup SDL stuff after exit() */
120 void InitPlatformDependentStuff(void)
122 #if defined(PLATFORM_MSDOS)
126 #if defined(PLATFORM_MACOSX)
127 updateUserGameDataDir();
130 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
134 #if defined(TARGET_SDL)
135 if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
136 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
142 void ClosePlatformDependentStuff(void)
144 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
148 #if defined(PLATFORM_MSDOS)
153 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
154 int real_sx, int real_sy,
155 int full_sxsize, int full_sysize,
156 Bitmap *field_save_buffer)
162 gfx.real_sx = real_sx;
163 gfx.real_sy = real_sy;
164 gfx.full_sxsize = full_sxsize;
165 gfx.full_sysize = full_sysize;
167 gfx.field_save_buffer = field_save_buffer;
170 gfx.background_bitmap = NULL;
171 gfx.background_bitmap_mask = REDRAW_NONE;
174 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
175 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
178 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
186 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
194 void InitGfxWindowInfo(int win_xsize, int win_ysize)
196 gfx.win_xsize = win_xsize;
197 gfx.win_ysize = win_ysize;
200 gfx.background_bitmap_mask = REDRAW_NONE;
202 ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
206 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
208 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
209 /* 2009-03-24: also (temporarily?) used for overlapping blit workaround */
210 gfx.scrollbuffer_width = scrollbuffer_width;
211 gfx.scrollbuffer_height = scrollbuffer_height;
214 void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
216 gfx.clipping_enabled = enabled;
219 gfx.clip_width = width;
220 gfx.clip_height = height;
223 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
225 gfx.draw_busy_anim_function = draw_busy_anim_function;
228 void InitGfxCustomArtworkInfo()
230 gfx.override_level_graphics = FALSE;
231 gfx.override_level_sounds = FALSE;
232 gfx.override_level_music = FALSE;
234 gfx.draw_init_text = TRUE;
237 void SetDrawDeactivationMask(int draw_deactivation_mask)
239 gfx.draw_deactivation_mask = draw_deactivation_mask;
242 void SetDrawBackgroundMask(int draw_background_mask)
244 gfx.draw_background_mask = draw_background_mask;
249 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
250 int dest_x, int dest_y, int width, int height)
252 int bitmap_xsize = width;
253 int bitmap_ysize = height;
254 int tile_xsize = tile->width;
255 int tile_ysize = tile->height;
256 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
257 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
260 for (y = 0; y < tile_ysteps; y++)
262 for (x = 0; x < tile_xsteps; x++)
264 int draw_x = dest_x + x * tile_xsize;
265 int draw_y = dest_y + y * tile_ysize;
266 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
267 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
269 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
274 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
276 if (background_bitmap_tile != NULL)
277 gfx.background_bitmap_mask |= mask;
279 gfx.background_bitmap_mask &= ~mask;
282 if (gfx.background_bitmap == NULL)
283 gfx.background_bitmap = CreateBitmap(video.width, video.height,
287 if (background_bitmap_tile == NULL) /* empty background requested */
290 if (mask == REDRAW_ALL)
291 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
292 0, 0, video.width, video.height);
293 else if (mask == REDRAW_FIELD)
294 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
295 gfx.real_sx, gfx.real_sy,
296 gfx.full_sxsize, gfx.full_sysize);
297 else if (mask == REDRAW_DOOR_1)
299 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
301 gfx.dxsize, gfx.dysize);
307 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
309 if (background_bitmap_tile != NULL)
310 gfx.background_bitmap_mask |= mask;
312 gfx.background_bitmap_mask &= ~mask;
315 if (gfx.background_bitmap == NULL)
316 gfx.background_bitmap = CreateBitmap(video.width, video.height,
320 if (background_bitmap_tile == NULL) /* empty background requested */
323 if (mask == REDRAW_ALL)
324 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
325 0, 0, video.width, video.height);
326 else if (mask == REDRAW_FIELD)
327 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
328 gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
329 else if (mask == REDRAW_DOOR_1)
331 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
332 gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
338 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
340 /* remove every mask before setting mask for window */
341 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
342 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
343 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
346 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
348 /* remove window area mask before setting mask for main area */
349 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
350 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
351 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
354 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
356 /* remove window area mask before setting mask for door area */
357 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
358 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
359 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
363 /* ========================================================================= */
364 /* video functions */
365 /* ========================================================================= */
367 inline static int GetRealDepth(int depth)
369 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
372 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
373 int width, int height, Pixel color)
375 #if defined(TARGET_SDL)
376 SDLFillRectangle(bitmap, x, y, width, height, color);
378 X11FillRectangle(bitmap, x, y, width, height, color);
382 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
383 int src_x, int src_y, int width, int height,
384 int dst_x, int dst_y, int mask_mode)
386 #if defined(TARGET_SDL)
387 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
388 dst_x, dst_y, mask_mode);
390 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
391 dst_x, dst_y, mask_mode);
395 void InitVideoDisplay(void)
397 #if defined(TARGET_SDL)
398 SDLInitVideoDisplay();
400 X11InitVideoDisplay();
404 void CloseVideoDisplay(void)
406 KeyboardAutoRepeatOn();
408 #if defined(TARGET_SDL)
409 SDL_QuitSubSystem(SDL_INIT_VIDEO);
412 XCloseDisplay(display);
416 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
419 video.height = height;
420 video.depth = GetRealDepth(depth);
422 video.fullscreen_available = FULLSCREEN_STATUS;
423 video.fullscreen_enabled = FALSE;
425 video.fullscreen_mode_current = NULL;
426 video.fullscreen_modes = NULL;
429 #if defined(TARGET_SDL)
430 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
432 X11InitVideoBuffer(&backbuffer, &window);
438 inline static void FreeBitmapPointers(Bitmap *bitmap)
443 #if defined(TARGET_SDL)
444 SDLFreeBitmapPointers(bitmap);
446 X11FreeBitmapPointers(bitmap);
449 checked_free(bitmap->source_filename);
450 bitmap->source_filename = NULL;
453 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
456 if (src_bitmap == NULL || dst_bitmap == NULL)
459 FreeBitmapPointers(dst_bitmap);
461 *dst_bitmap = *src_bitmap;
464 void FreeBitmap(Bitmap *bitmap)
469 FreeBitmapPointers(bitmap);
474 Bitmap *CreateBitmapStruct(void)
476 #if defined(TARGET_SDL)
477 return checked_calloc(sizeof(struct SDLSurfaceInfo));
479 return checked_calloc(sizeof(struct X11DrawableInfo));
483 Bitmap *CreateBitmap(int width, int height, int depth)
485 Bitmap *new_bitmap = CreateBitmapStruct();
486 int real_width = MAX(1, width); /* prevent zero bitmap width */
487 int real_height = MAX(1, height); /* prevent zero bitmap height */
488 int real_depth = GetRealDepth(depth);
490 #if defined(TARGET_SDL)
491 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
493 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
496 new_bitmap->width = real_width;
497 new_bitmap->height = real_height;
502 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
504 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
508 *bitmap = new_bitmap;
512 TransferBitmapPointers(new_bitmap, *bitmap);
517 void CloseWindow(DrawWindow *window)
519 #if defined(TARGET_X11)
520 X11CloseWindow(window);
524 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
527 if (draw_mask == REDRAW_NONE)
530 if (draw_mask & REDRAW_ALL)
533 if ((draw_mask & REDRAW_FIELD) &&
534 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
537 if ((draw_mask & REDRAW_DOOR_1) &&
538 x >= gfx.dx && y < gfx.dy + gfx.dysize)
541 if ((draw_mask & REDRAW_DOOR_2) &&
542 x >= gfx.dx && y >= gfx.vy)
548 boolean DrawingDeactivated(int x, int y, int width, int height)
550 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
553 boolean DrawingOnBackground(int x, int y)
555 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
556 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
559 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
560 int *width, int *height, boolean is_dest)
563 int clip_x, clip_y, clip_width, clip_height;
565 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
567 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
568 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
569 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
570 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
576 clip_width = bitmap->width;
577 clip_height = bitmap->height;
580 /* skip if rectangle completely outside bitmap */
582 if (*x + *width <= clip_x ||
583 *y + *height <= clip_y ||
584 *x >= clip_x + clip_width ||
585 *y >= clip_y + clip_height)
588 /* clip if rectangle overlaps bitmap */
592 *width -= clip_x - *x;
595 else if (*x + *width > clip_x + clip_width)
597 *width = clip_x + clip_width - *x;
602 *height -= clip_y - *y;
605 else if (*y + *height > clip_y + clip_height)
607 *height = clip_y + clip_height - *y;
614 /* skip if rectangle completely outside bitmap */
616 if (*x + *width <= 0 ||
618 *x >= bitmap->width ||
619 *y >= bitmap->height)
622 /* clip if rectangle overlaps bitmap */
629 else if (*x + *width > bitmap->width)
631 *width = bitmap->width - *x;
639 else if (*y + *height > bitmap->height)
641 *height = bitmap->height - *y;
648 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
649 int src_x, int src_y, int width, int height,
650 int dst_x, int dst_y)
652 int dst_x_unclipped = dst_x;
653 int dst_y_unclipped = dst_y;
655 if (DrawingDeactivated(dst_x, dst_y, width, height))
659 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
660 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
663 /* source x/y might need adjustment if destination x/y was clipped top/left */
664 src_x += dst_x - dst_x_unclipped;
665 src_y += dst_y - dst_y_unclipped;
668 /* skip if rectangle starts outside bitmap */
669 if (src_x >= src_bitmap->width ||
670 src_y >= src_bitmap->height ||
671 dst_x >= dst_bitmap->width ||
672 dst_y >= dst_bitmap->height)
675 /* clip if rectangle overlaps bitmap */
676 if (src_x + width > src_bitmap->width)
677 width = src_bitmap->width - src_x;
678 if (src_y + height > src_bitmap->height)
679 height = src_bitmap->height - src_y;
680 if (dst_x + width > dst_bitmap->width)
681 width = dst_bitmap->width - dst_x;
682 if (dst_y + height > dst_bitmap->height)
683 height = dst_bitmap->height - dst_y;
687 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
688 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
689 but is already fixed in SVN and should therefore finally be fixed with
690 the next official SDL release, which is probably version 1.2.14.) */
692 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
693 #if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
694 if (src_bitmap == dst_bitmap)
696 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
698 /* needed when blitting directly to same bitmap -- should not be needed with
699 recent SDL libraries, but apparently does not work in 1.2.11 directly */
701 static Bitmap *tmp_bitmap = NULL;
702 static int tmp_bitmap_xsize = 0;
703 static int tmp_bitmap_ysize = 0;
705 /* start with largest static bitmaps for initial bitmap size ... */
706 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
708 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
709 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
712 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
713 if (src_bitmap->width > tmp_bitmap_xsize ||
714 src_bitmap->height > tmp_bitmap_ysize)
716 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
717 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
719 FreeBitmap(tmp_bitmap);
724 if (tmp_bitmap == NULL)
725 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
728 sysCopyArea(src_bitmap, tmp_bitmap,
729 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
730 sysCopyArea(tmp_bitmap, dst_bitmap,
731 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
739 sysCopyArea(src_bitmap, dst_bitmap,
740 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
743 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
744 int src_x, int src_y, int src_width, int src_height,
745 int dst_x, int dst_y, int dst_width, int dst_height)
747 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
748 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
749 int dst_xsize = dst_width;
750 int dst_ysize = dst_height;
751 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
752 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
755 for (y = 0; y < src_ysteps; y++)
757 for (x = 0; x < src_xsteps; x++)
759 int draw_x = dst_x + x * src_xsize;
760 int draw_y = dst_y + y * src_ysize;
761 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
762 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
764 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
770 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
771 int fade_mode, int fade_delay, int post_delay,
772 void (*draw_border_function)(void))
775 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
776 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
780 #if defined(TARGET_SDL)
781 SDLFadeRectangle(bitmap_cross, x, y, width, height,
782 fade_mode, fade_delay, post_delay, draw_border_function);
784 X11FadeRectangle(bitmap_cross, x, y, width, height,
785 fade_mode, fade_delay, post_delay, draw_border_function);
789 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
792 if (DrawingDeactivated(x, y, width, height))
796 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
799 /* skip if rectangle starts outside bitmap */
800 if (x >= bitmap->width ||
804 /* clip if rectangle overlaps bitmap */
805 if (x + width > bitmap->width)
806 width = bitmap->width - x;
807 if (y + height > bitmap->height)
808 height = bitmap->height - y;
811 sysFillRectangle(bitmap, x, y, width, height, color);
814 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
816 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
819 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
820 int width, int height)
822 if (DrawingOnBackground(x, y))
823 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
825 ClearRectangle(bitmap, x, y, width, height);
828 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
830 #if defined(TARGET_X11)
833 bitmap->clip_gc = clip_gc;
834 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
839 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
841 #if defined(TARGET_X11)
844 bitmap->clip_gc = clip_gc;
845 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
850 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
851 int src_x, int src_y, int width, int height,
852 int dst_x, int dst_y)
854 if (DrawingDeactivated(dst_x, dst_y, width, height))
857 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
858 dst_x, dst_y, BLIT_MASKED);
861 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
862 int src_x, int src_y, int width, int height,
863 int dst_x, int dst_y)
865 if (DrawingOnBackground(dst_x, dst_y))
867 /* draw background */
868 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
871 /* draw foreground */
872 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
873 dst_x - src_x, dst_y - src_y);
874 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
878 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
882 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
885 #if defined(TARGET_SDL)
886 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
888 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
892 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
895 #if defined(TARGET_SDL)
896 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
898 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
902 #if !defined(TARGET_X11_NATIVE)
903 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
904 int to_x, int to_y, Pixel pixel, int line_width)
908 for (x = 0; x < line_width; x++)
910 for (y = 0; y < line_width; y++)
912 int dx = x - line_width / 2;
913 int dy = y - line_width / 2;
915 if ((x == 0 && y == 0) ||
916 (x == 0 && y == line_width - 1) ||
917 (x == line_width - 1 && y == 0) ||
918 (x == line_width - 1 && y == line_width - 1))
921 #if defined(TARGET_SDL)
923 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
924 #elif defined(TARGET_ALLEGRO)
925 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
926 to_x + dx, to_y + dy, pixel);
933 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
935 #if !defined(TARGET_X11_NATIVE)
939 for (i = 0; i < num_points - 1; i++)
940 DrawLine(bitmap, points[i].x, points[i].y,
941 points[i + 1].x, points[i + 1].y, pixel, line_width);
944 SDLDrawLines(bitmap->surface, points, num_points, pixel);
947 XSetForeground(display, bitmap->line_gc[1], pixel);
948 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
949 (XPoint *)points, num_points, CoordModeOrigin);
953 Pixel GetPixel(Bitmap *bitmap, int x, int y)
955 if (x < 0 || x >= bitmap->width ||
956 y < 0 || y >= bitmap->height)
959 #if defined(TARGET_SDL)
960 return SDLGetPixel(bitmap, x, y);
961 #elif defined(TARGET_ALLEGRO)
962 return AllegroGetPixel(bitmap->drawable, x, y);
964 return X11GetPixel(bitmap, x, y);
968 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
969 unsigned int color_g, unsigned int color_b)
971 #if defined(TARGET_SDL)
972 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
973 #elif defined(TARGET_ALLEGRO)
974 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
976 return X11GetPixelFromRGB(color_r, color_g, color_b);
980 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
982 unsigned int color_r = (color >> 16) & 0xff;
983 unsigned int color_g = (color >> 8) & 0xff;
984 unsigned int color_b = (color >> 0) & 0xff;
986 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
989 /* execute all pending screen drawing operations */
990 void FlushDisplay(void)
997 /* execute and wait for all pending screen drawing operations */
998 void SyncDisplay(void)
1001 XSync(display, FALSE);
1005 void KeyboardAutoRepeatOn(void)
1007 #if defined(TARGET_SDL)
1008 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
1009 SDL_DEFAULT_REPEAT_INTERVAL / 2);
1010 SDL_EnableUNICODE(1);
1013 XAutoRepeatOn(display);
1017 void KeyboardAutoRepeatOff(void)
1019 #if defined(TARGET_SDL)
1020 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1021 SDL_EnableUNICODE(0);
1024 XAutoRepeatOff(display);
1028 boolean PointerInWindow(DrawWindow *window)
1030 #if defined(TARGET_SDL)
1038 /* if XQueryPointer() returns False, the pointer
1039 is not on the same screen as the specified window */
1040 return XQueryPointer(display, window->drawable, &root, &child,
1041 &root_x, &root_y, &win_x, &win_y, &mask);
1045 boolean SetVideoMode(boolean fullscreen)
1047 #if defined(TARGET_SDL)
1048 return SDLSetVideoMode(&backbuffer, fullscreen);
1050 boolean success = TRUE;
1052 if (fullscreen && video.fullscreen_available)
1054 Error(ERR_WARN, "fullscreen not available in X11 version");
1056 /* display error message only once */
1057 video.fullscreen_available = FALSE;
1066 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1068 #if defined(TARGET_SDL)
1069 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1070 (!fullscreen && video.fullscreen_enabled))
1071 fullscreen = SetVideoMode(fullscreen);
1077 Bitmap *LoadImage(char *filename)
1081 #if defined(TARGET_SDL)
1082 new_bitmap = SDLLoadImage(filename);
1084 new_bitmap = X11LoadImage(filename);
1088 new_bitmap->source_filename = getStringCopy(filename);
1093 Bitmap *LoadCustomImage(char *basename)
1095 char *filename = getCustomImageFilename(basename);
1098 if (filename == NULL)
1099 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1101 if ((new_bitmap = LoadImage(filename)) == NULL)
1102 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1107 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1109 char *filename = getCustomImageFilename(basename);
1112 if (filename == NULL) /* (should never happen) */
1114 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1118 if (strEqual(filename, bitmap->source_filename))
1120 /* The old and new image are the same (have the same filename and path).
1121 This usually means that this image does not exist in this graphic set
1122 and a fallback to the existing image is done. */
1127 if ((new_bitmap = LoadImage(filename)) == NULL)
1129 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1133 if (bitmap->width != new_bitmap->width ||
1134 bitmap->height != new_bitmap->height)
1136 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1138 FreeBitmap(new_bitmap);
1142 TransferBitmapPointers(new_bitmap, bitmap);
1146 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1148 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1150 #if defined(TARGET_SDL)
1151 SDLZoomBitmap(src_bitmap, dst_bitmap);
1153 X11ZoomBitmap(src_bitmap, dst_bitmap);
1159 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1160 boolean create_small_bitmaps)
1164 Bitmap *tmp_bitmap_1;
1165 Bitmap *tmp_bitmap_2;
1166 Bitmap *tmp_bitmap_4;
1167 Bitmap *tmp_bitmap_8;
1168 Bitmap *tmp_bitmap_16;
1169 Bitmap *tmp_bitmap_32;
1170 int width_1, height_1;
1171 int width_2, height_2;
1172 int width_4, height_4;
1173 int width_8, height_8;
1174 int width_16, height_16;
1175 int width_32, height_32;
1176 int new_width, new_height;
1178 /* calculate new image dimensions for normal sized image */
1179 width_1 = old_bitmap->width * zoom_factor;
1180 height_1 = old_bitmap->height * zoom_factor;
1182 /* get image with normal size (this might require scaling up) */
1183 if (zoom_factor != 1)
1184 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1186 tmp_bitmap_1 = old_bitmap;
1188 /* this is only needed to make compilers happy */
1189 tmp_bitmap_2 = NULL;
1190 tmp_bitmap_4 = NULL;
1191 tmp_bitmap_8 = NULL;
1192 tmp_bitmap_16 = NULL;
1193 tmp_bitmap_32 = NULL;
1195 if (create_small_bitmaps)
1197 /* calculate new image dimensions for small images */
1198 width_2 = width_1 / 2;
1199 height_2 = height_1 / 2;
1200 width_4 = width_1 / 4;
1201 height_4 = height_1 / 4;
1202 width_8 = width_1 / 8;
1203 height_8 = height_1 / 8;
1204 width_16 = width_1 / 16;
1205 height_16 = height_1 / 16;
1206 width_32 = width_1 / 32;
1207 height_32 = height_1 / 32;
1209 UPDATE_BUSY_STATE();
1211 /* get image with 1/2 of normal size (for use in the level editor) */
1212 if (zoom_factor != 2)
1213 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1215 tmp_bitmap_2 = old_bitmap;
1217 UPDATE_BUSY_STATE();
1219 /* get image with 1/4 of normal size (for use in the level editor) */
1220 if (zoom_factor != 4)
1221 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1223 tmp_bitmap_4 = old_bitmap;
1225 UPDATE_BUSY_STATE();
1227 /* get image with 1/8 of normal size (for use on the preview screen) */
1228 if (zoom_factor != 8)
1229 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1231 tmp_bitmap_8 = old_bitmap;
1233 UPDATE_BUSY_STATE();
1235 /* get image with 1/16 of normal size (for use on the preview screen) */
1236 if (zoom_factor != 16)
1237 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1239 tmp_bitmap_16 = old_bitmap;
1241 UPDATE_BUSY_STATE();
1243 /* get image with 1/32 of normal size (for use on the preview screen) */
1244 if (zoom_factor != 32)
1245 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1247 tmp_bitmap_32 = old_bitmap;
1249 UPDATE_BUSY_STATE();
1253 /* if image was scaled up, create new clipmask for normal size image */
1254 if (zoom_factor != 1)
1256 #if defined(TARGET_X11)
1257 if (old_bitmap->clip_mask)
1258 XFreePixmap(display, old_bitmap->clip_mask);
1260 old_bitmap->clip_mask =
1261 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
1263 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1265 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1267 if (old_bitmap->surface_masked)
1268 SDL_FreeSurface(old_bitmap->surface_masked);
1270 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
1271 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1272 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1273 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1274 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
1279 if (create_small_bitmaps)
1281 new_width = width_1;
1282 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1284 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1286 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1287 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1289 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1290 width_1 / 2, height_1);
1291 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1292 3 * width_1 / 4, height_1);
1293 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1294 7 * width_1 / 8, height_1);
1295 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1296 15 * width_1 / 16, height_1);
1298 UPDATE_BUSY_STATE();
1302 new_width = width_1;
1303 new_height = height_1;
1305 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1308 if (create_small_bitmaps)
1310 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1311 if (zoom_factor != 1)
1312 FreeBitmap(tmp_bitmap_1);
1314 if (zoom_factor != 2)
1315 FreeBitmap(tmp_bitmap_2);
1317 if (zoom_factor != 4)
1318 FreeBitmap(tmp_bitmap_4);
1320 if (zoom_factor != 8)
1321 FreeBitmap(tmp_bitmap_8);
1323 if (zoom_factor != 16)
1324 FreeBitmap(tmp_bitmap_16);
1326 if (zoom_factor != 32)
1327 FreeBitmap(tmp_bitmap_32);
1330 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1331 #if defined(TARGET_SDL)
1332 swap_bitmap.surface = old_bitmap->surface;
1333 old_bitmap->surface = new_bitmap->surface;
1334 new_bitmap->surface = swap_bitmap.surface;
1336 swap_bitmap.drawable = old_bitmap->drawable;
1337 old_bitmap->drawable = new_bitmap->drawable;
1338 new_bitmap->drawable = swap_bitmap.drawable;
1341 old_bitmap->width = new_bitmap->width;
1342 old_bitmap->height = new_bitmap->height;
1345 /* this replaces all blit masks created when loading -- maybe optimize this */
1347 #if defined(TARGET_X11)
1348 if (old_bitmap->clip_mask)
1349 XFreePixmap(display, old_bitmap->clip_mask);
1351 old_bitmap->clip_mask =
1352 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1354 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1356 SDL_Surface *old_surface = old_bitmap->surface;
1358 if (old_bitmap->surface_masked)
1359 SDL_FreeSurface(old_bitmap->surface_masked);
1361 SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
1362 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1363 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1364 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1365 SDL_SetColorKey(old_surface, 0, 0); /* reset transparent pixel */
1370 UPDATE_BUSY_STATE();
1372 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1375 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1377 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1380 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1382 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1386 /* ------------------------------------------------------------------------- */
1387 /* mouse pointer functions */
1388 /* ------------------------------------------------------------------------- */
1390 #if !defined(PLATFORM_MSDOS)
1391 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1392 /* XPM image definitions */
1393 static const char *cursor_image_none[] =
1395 /* width height num_colors chars_per_pixel */
1424 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1425 static const char *cursor_image_dot[] =
1427 /* width height num_colors chars_per_pixel */
1456 static const char **cursor_image_playfield = cursor_image_dot;
1458 /* some people complained about a "white dot" on the screen and thought it
1459 was a graphical error... OK, let's just remove the whole pointer :-) */
1460 static const char **cursor_image_playfield = cursor_image_none;
1463 #if defined(TARGET_SDL)
1464 static const int cursor_bit_order = BIT_ORDER_MSB;
1465 #elif defined(TARGET_X11_NATIVE)
1466 static const int cursor_bit_order = BIT_ORDER_LSB;
1469 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1471 struct MouseCursorInfo *cursor;
1472 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1473 int header_lines = 4;
1476 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1478 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1481 for (y = 0; y < cursor->width; y++)
1483 for (x = 0; x < cursor->height; x++)
1486 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1491 cursor->data[i] = cursor->mask[i] = 0;
1494 switch (image[header_lines + y][x])
1497 cursor->data[i] |= bit_mask;
1498 cursor->mask[i] |= bit_mask;
1502 cursor->mask[i] |= bit_mask;
1511 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1515 #endif /* !PLATFORM_MSDOS */
1517 void SetMouseCursor(int mode)
1519 #if !defined(PLATFORM_MSDOS)
1520 static struct MouseCursorInfo *cursor_none = NULL;
1521 static struct MouseCursorInfo *cursor_playfield = NULL;
1522 struct MouseCursorInfo *cursor_new;
1524 if (cursor_none == NULL)
1525 cursor_none = get_cursor_from_image(cursor_image_none);
1527 if (cursor_playfield == NULL)
1528 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1530 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1531 mode == CURSOR_NONE ? cursor_none :
1532 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1534 #if defined(TARGET_SDL)
1535 SDLSetMouseCursor(cursor_new);
1536 #elif defined(TARGET_X11_NATIVE)
1537 X11SetMouseCursor(cursor_new);
1543 /* ========================================================================= */
1544 /* audio functions */
1545 /* ========================================================================= */
1547 void OpenAudio(void)
1549 /* always start with reliable default values */
1550 audio.sound_available = FALSE;
1551 audio.music_available = FALSE;
1552 audio.loops_available = FALSE;
1554 audio.sound_enabled = FALSE;
1555 audio.sound_deactivated = FALSE;
1557 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1558 audio.mixer_pid = 0;
1559 audio.device_name = NULL;
1560 audio.device_fd = -1;
1562 audio.num_channels = 0;
1563 audio.music_channel = 0;
1564 audio.first_sound_channel = 0;
1566 #if defined(TARGET_SDL)
1568 #elif defined(PLATFORM_UNIX)
1570 #elif defined(PLATFORM_MSDOS)
1575 void CloseAudio(void)
1577 #if defined(TARGET_SDL)
1579 #elif defined(PLATFORM_UNIX)
1581 #elif defined(PLATFORM_MSDOS)
1585 audio.sound_enabled = FALSE;
1588 void SetAudioMode(boolean enabled)
1590 if (!audio.sound_available)
1593 audio.sound_enabled = enabled;
1597 /* ========================================================================= */
1598 /* event functions */
1599 /* ========================================================================= */
1601 void InitEventFilter(EventFilter filter_function)
1603 #if defined(TARGET_SDL)
1604 /* set event filter to filter out certain events */
1605 SDL_SetEventFilter(filter_function);
1609 boolean PendingEvent(void)
1611 #if defined(TARGET_SDL)
1612 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1614 return (XPending(display) ? TRUE : FALSE);
1618 void NextEvent(Event *event)
1620 #if defined(TARGET_SDL)
1621 SDLNextEvent(event);
1623 XNextEvent(display, event);
1627 void PeekEvent(Event *event)
1629 #if defined(TARGET_SDL)
1630 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1632 XPeekEvent(display, event);
1636 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1638 #if defined(TARGET_SDL)
1641 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1642 (int)event->keysym.unicode,
1643 (int)event->keysym.sym,
1644 (int)SDL_GetModState());
1647 if (with_modifiers &&
1648 event->keysym.unicode > 0x0000 &&
1649 event->keysym.unicode < 0x2000)
1650 return event->keysym.unicode;
1652 return event->keysym.sym;
1657 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1658 (int)XLookupKeysym(event, event->state),
1659 (int)XLookupKeysym(event, 0));
1663 return XLookupKeysym(event, event->state);
1665 return XLookupKeysym(event, 0);
1669 KeyMod HandleKeyModState(Key key, int key_status)
1671 static KeyMod current_modifiers = KMOD_None;
1673 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1675 KeyMod new_modifier = KMOD_None;
1680 new_modifier = KMOD_Shift_L;
1683 new_modifier = KMOD_Shift_R;
1685 case KSYM_Control_L:
1686 new_modifier = KMOD_Control_L;
1688 case KSYM_Control_R:
1689 new_modifier = KMOD_Control_R;
1692 new_modifier = KMOD_Meta_L;
1695 new_modifier = KMOD_Meta_R;
1698 new_modifier = KMOD_Alt_L;
1701 new_modifier = KMOD_Alt_R;
1707 if (key_status == KEY_PRESSED)
1708 current_modifiers |= new_modifier;
1710 current_modifiers &= ~new_modifier;
1713 return current_modifiers;
1716 KeyMod GetKeyModState()
1718 #if defined(TARGET_SDL)
1719 return (KeyMod)SDL_GetModState();
1721 return HandleKeyModState(KSYM_UNDEFINED, 0);
1725 KeyMod GetKeyModStateFromEvents()
1727 /* always use key modifier state as tracked from key events (this is needed
1728 if the modifier key event was injected into the event queue, but the key
1729 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1730 query the keys as held pressed on the keyboard) -- this case is currently
1731 only used to filter out clipboard insert events from "True X-Mouse" tool */
1733 return HandleKeyModState(KSYM_UNDEFINED, 0);
1736 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1738 if (event->type != EVENT_CLIENTMESSAGE)
1741 #if defined(TARGET_SDL)
1742 return TRUE; /* the only possible message here is SDL_QUIT */
1743 #elif defined(PLATFORM_UNIX)
1744 if ((event->window == window->drawable) &&
1745 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1753 /* ========================================================================= */
1754 /* joystick functions */
1755 /* ========================================================================= */
1757 void InitJoysticks()
1761 #if defined(NO_JOYSTICK)
1762 return; /* joysticks generally deactivated by compile-time directive */
1765 /* always start with reliable default values */
1766 joystick.status = JOYSTICK_NOT_AVAILABLE;
1767 for (i = 0; i < MAX_PLAYERS; i++)
1768 joystick.fd[i] = -1; /* joystick device closed */
1770 #if defined(TARGET_SDL)
1772 #elif defined(PLATFORM_UNIX)
1773 UnixInitJoysticks();
1774 #elif defined(PLATFORM_MSDOS)
1775 MSDOSInitJoysticks();
1779 for (i = 0; i < MAX_PLAYERS; i++)
1780 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1784 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1786 #if defined(TARGET_SDL)
1787 return SDLReadJoystick(nr, x, y, b1, b2);
1788 #elif defined(PLATFORM_UNIX)
1789 return UnixReadJoystick(nr, x, y, b1, b2);
1790 #elif defined(PLATFORM_MSDOS)
1791 return MSDOSReadJoystick(nr, x, y, b1, b2);