1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
25 /* ========================================================================= */
26 /* exported variables */
27 /* ========================================================================= */
29 struct ProgramInfo program;
30 struct OptionInfo options;
31 struct VideoSystemInfo video;
32 struct AudioSystemInfo audio;
34 struct ArtworkInfo artwork;
35 struct JoystickInfo joystick;
36 struct SetupInfo setup;
38 LevelDirTree *leveldir_first_all = NULL;
39 LevelDirTree *leveldir_first = NULL;
40 LevelDirTree *leveldir_current = NULL;
43 struct LevelStats level_stats[MAX_LEVELS];
45 Display *display = NULL;
46 Visual *visual = NULL;
50 DrawWindow *window = NULL;
51 DrawBuffer *backbuffer = NULL;
52 DrawBuffer *drawto = NULL;
54 int button_status = MB_NOT_PRESSED;
55 boolean motion_status = FALSE;
56 #if defined(TARGET_SDL2)
57 boolean keyrepeat_status = TRUE;
60 int redraw_mask = REDRAW_NONE;
66 /* ========================================================================= */
67 /* init/close functions */
68 /* ========================================================================= */
70 void InitProgramInfo(char *argv0,
71 char *userdata_subdir, char *userdata_subdir_unix,
72 char *program_title, char *icon_title,
73 char *sdl_icon_filename, char *cookie_prefix,
76 program.command_basepath = getBasePath(argv0);
77 program.command_basename = getBaseName(argv0);
79 program.userdata_subdir = userdata_subdir;
80 program.userdata_subdir_unix = userdata_subdir_unix;
81 program.userdata_path = getUserGameDataDir();
83 program.program_title = program_title;
84 program.window_title = "(undefined)";
85 program.icon_title = icon_title;
87 program.sdl_icon_filename = sdl_icon_filename;
89 program.cookie_prefix = cookie_prefix;
91 program.version_major = VERSION_MAJOR(program_version);
92 program.version_minor = VERSION_MINOR(program_version);
93 program.version_patch = VERSION_PATCH(program_version);
94 program.version_build = VERSION_BUILD(program_version);
95 program.version_ident = program_version;
97 program.error_filename = getErrorFilename(ERROR_BASENAME);
98 program.error_file = stderr;
101 void SetWindowTitle()
103 program.window_title = program.window_title_function();
105 #if defined(TARGET_SDL)
110 void InitWindowTitleFunction(char *(*window_title_function)(void))
112 program.window_title_function = window_title_function;
115 void InitExitMessageFunction(void (*exit_message_function)(char *, va_list))
117 program.exit_message_function = exit_message_function;
120 void InitExitFunction(void (*exit_function)(int))
122 program.exit_function = exit_function;
124 /* set signal handlers to custom exit function */
125 signal(SIGINT, exit_function);
126 signal(SIGTERM, exit_function);
128 #if defined(TARGET_SDL)
129 /* set exit function to automatically cleanup SDL stuff after exit() */
134 void InitPlatformDependentStuff(void)
136 // this is initialized in GetOptions(), but may already be used before
137 options.verbose = TRUE;
139 #if defined(PLATFORM_MACOSX)
140 updateUserGameDataDir();
146 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
151 #if defined(TARGET_SDL)
152 #if defined(TARGET_SDL2)
153 int sdl_init_flags = SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE;
155 int sdl_init_flags = SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE;
158 if (SDL_Init(sdl_init_flags) < 0)
159 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
165 void ClosePlatformDependentStuff(void)
167 #if defined(PLATFORM_WIN32)
172 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
173 int real_sx, int real_sy,
174 int full_sxsize, int full_sysize,
175 Bitmap *field_save_buffer)
181 gfx.real_sx = real_sx;
182 gfx.real_sy = real_sy;
183 gfx.full_sxsize = full_sxsize;
184 gfx.full_sysize = full_sysize;
186 gfx.field_save_buffer = field_save_buffer;
189 gfx.background_bitmap = NULL;
190 gfx.background_bitmap_mask = REDRAW_NONE;
193 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
194 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
197 void InitGfxTileSizeInfo(int game_tile_size, int standard_tile_size)
199 gfx.game_tile_size = game_tile_size;
200 gfx.standard_tile_size = standard_tile_size;
203 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
211 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
219 void InitGfxDoor3Info(int ex, int ey, int exsize, int eysize)
227 void InitGfxWindowInfo(int win_xsize, int win_ysize)
229 gfx.win_xsize = win_xsize;
230 gfx.win_ysize = win_ysize;
233 gfx.background_bitmap_mask = REDRAW_NONE;
235 ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
239 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
241 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
242 /* 2009-03-24: also (temporarily?) used for overlapping blit workaround */
243 gfx.scrollbuffer_width = scrollbuffer_width;
244 gfx.scrollbuffer_height = scrollbuffer_height;
247 void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
249 gfx.clipping_enabled = enabled;
252 gfx.clip_width = width;
253 gfx.clip_height = height;
256 void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
258 gfx.draw_busy_anim_function = draw_busy_anim_function;
261 void InitGfxCustomArtworkInfo()
263 gfx.override_level_graphics = FALSE;
264 gfx.override_level_sounds = FALSE;
265 gfx.override_level_music = FALSE;
267 gfx.draw_init_text = TRUE;
270 void SetDrawDeactivationMask(int draw_deactivation_mask)
272 gfx.draw_deactivation_mask = draw_deactivation_mask;
275 void SetDrawBackgroundMask(int draw_background_mask)
277 gfx.draw_background_mask = draw_background_mask;
282 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
283 int dest_x, int dest_y, int width, int height)
285 int bitmap_xsize = width;
286 int bitmap_ysize = height;
287 int tile_xsize = tile->width;
288 int tile_ysize = tile->height;
289 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
290 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
293 for (y = 0; y < tile_ysteps; y++)
295 for (x = 0; x < tile_xsteps; x++)
297 int draw_x = dest_x + x * tile_xsize;
298 int draw_y = dest_y + y * tile_ysize;
299 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
300 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
302 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
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 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
325 0, 0, video.width, video.height);
326 else if (mask == REDRAW_FIELD)
327 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
328 gfx.real_sx, gfx.real_sy,
329 gfx.full_sxsize, gfx.full_sysize);
330 else if (mask == REDRAW_DOOR_1)
331 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
333 gfx.dxsize, gfx.dysize);
338 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
340 if (background_bitmap_tile != NULL)
341 gfx.background_bitmap_mask |= mask;
343 gfx.background_bitmap_mask &= ~mask;
346 if (gfx.background_bitmap == NULL)
347 gfx.background_bitmap = CreateBitmap(video.width, video.height,
351 if (background_bitmap_tile == NULL) /* empty background requested */
354 if (mask == REDRAW_ALL)
355 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
356 0, 0, video.width, video.height);
357 else if (mask == REDRAW_FIELD)
358 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
359 gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
360 else if (mask == REDRAW_DOOR_1)
361 BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
362 gfx.dx, gfx.dy, gfx.dxsize, gfx.dysize);
367 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
369 /* remove every mask before setting mask for window */
370 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
371 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
372 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
375 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
377 /* remove window area mask before setting mask for main area */
378 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
379 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
380 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
383 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
385 /* remove window area mask before setting mask for door area */
386 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
387 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
388 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
392 /* ========================================================================= */
393 /* video functions */
394 /* ========================================================================= */
396 inline static int GetRealDepth(int depth)
398 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
401 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
402 int width, int height, Pixel color)
404 SDLFillRectangle(bitmap, x, y, width, height, color);
407 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
408 int src_x, int src_y, int width, int height,
409 int dst_x, int dst_y, int mask_mode)
411 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
412 dst_x, dst_y, mask_mode);
415 void LimitScreenUpdates(boolean enable)
417 #if defined(TARGET_SDL)
418 SDLLimitScreenUpdates(enable);
422 void InitVideoDisplay(void)
424 SDLInitVideoDisplay();
427 void CloseVideoDisplay(void)
429 KeyboardAutoRepeatOn();
431 #if defined(TARGET_SDL)
432 SDL_QuitSubSystem(SDL_INIT_VIDEO);
435 XCloseDisplay(display);
439 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
442 printf("::: InitVideoBuffer\n");
446 video.height = height;
447 video.depth = GetRealDepth(depth);
449 video.fullscreen_available = FULLSCREEN_STATUS;
450 video.fullscreen_enabled = FALSE;
451 // video.fullscreen_initial = FALSE;
453 video.fullscreen_mode_current = NULL;
454 video.fullscreen_modes = NULL;
457 video.window_scaling_available = WINDOW_SCALING_STATUS;
459 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
464 inline static void FreeBitmapPointers(Bitmap *bitmap)
469 SDLFreeBitmapPointers(bitmap);
471 checked_free(bitmap->source_filename);
472 bitmap->source_filename = NULL;
475 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
478 if (src_bitmap == NULL || dst_bitmap == NULL)
481 FreeBitmapPointers(dst_bitmap);
483 *dst_bitmap = *src_bitmap;
486 void FreeBitmap(Bitmap *bitmap)
491 FreeBitmapPointers(bitmap);
496 Bitmap *CreateBitmapStruct(void)
498 return checked_calloc(sizeof(struct SDLSurfaceInfo));
501 Bitmap *CreateBitmap(int width, int height, int depth)
503 Bitmap *new_bitmap = CreateBitmapStruct();
504 int real_width = MAX(1, width); /* prevent zero bitmap width */
505 int real_height = MAX(1, height); /* prevent zero bitmap height */
506 int real_depth = GetRealDepth(depth);
508 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
510 new_bitmap->width = real_width;
511 new_bitmap->height = real_height;
516 void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
518 Bitmap *new_bitmap = CreateBitmap(width, height, depth);
522 *bitmap = new_bitmap;
526 TransferBitmapPointers(new_bitmap, *bitmap);
531 void CloseWindow(DrawWindow *window)
535 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
538 if (draw_mask == REDRAW_NONE)
541 if (draw_mask & REDRAW_ALL)
545 if ((draw_mask & REDRAW_FIELD) && IN_GFX_FIELD_FULL(x, y))
548 if ((draw_mask & REDRAW_DOOR_1) && IN_GFX_DOOR_1(x, y))
551 if ((draw_mask & REDRAW_DOOR_2) && IN_GFX_DOOR_2(x, y))
554 if ((draw_mask & REDRAW_DOOR_3) && IN_GFX_DOOR_3(x, y))
557 if ((draw_mask & REDRAW_FIELD) &&
558 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
561 if ((draw_mask & REDRAW_DOOR_1) &&
562 x >= gfx.dx && y < gfx.dy + gfx.dysize)
565 if ((draw_mask & REDRAW_DOOR_2) &&
566 x >= gfx.dx && y >= gfx.vy)
573 boolean DrawingDeactivated(int x, int y, int width, int height)
575 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
578 boolean DrawingOnBackground(int x, int y)
580 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
581 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
584 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
585 int *width, int *height, boolean is_dest)
588 int clip_x, clip_y, clip_width, clip_height;
590 if (gfx.clipping_enabled && is_dest) /* only clip destination bitmap */
592 clip_x = MIN(MAX(0, gfx.clip_x), bitmap->width);
593 clip_y = MIN(MAX(0, gfx.clip_y), bitmap->height);
594 clip_width = MIN(MAX(0, gfx.clip_width), bitmap->width - clip_x);
595 clip_height = MIN(MAX(0, gfx.clip_height), bitmap->height - clip_y);
601 clip_width = bitmap->width;
602 clip_height = bitmap->height;
605 /* skip if rectangle completely outside bitmap */
607 if (*x + *width <= clip_x ||
608 *y + *height <= clip_y ||
609 *x >= clip_x + clip_width ||
610 *y >= clip_y + clip_height)
613 /* clip if rectangle overlaps bitmap */
617 *width -= clip_x - *x;
620 else if (*x + *width > clip_x + clip_width)
622 *width = clip_x + clip_width - *x;
627 *height -= clip_y - *y;
630 else if (*y + *height > clip_y + clip_height)
632 *height = clip_y + clip_height - *y;
639 /* skip if rectangle completely outside bitmap */
641 if (*x + *width <= 0 ||
643 *x >= bitmap->width ||
644 *y >= bitmap->height)
647 /* clip if rectangle overlaps bitmap */
654 else if (*x + *width > bitmap->width)
656 *width = bitmap->width - *x;
664 else if (*y + *height > bitmap->height)
666 *height = bitmap->height - *y;
673 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
674 int src_x, int src_y, int width, int height,
675 int dst_x, int dst_y)
677 int dst_x_unclipped = dst_x;
678 int dst_y_unclipped = dst_y;
680 if (src_bitmap == NULL || dst_bitmap == NULL)
683 if (DrawingDeactivated(dst_x, dst_y, width, height))
687 if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
688 !InClippedRectangle(dst_bitmap, &dst_x, &dst_y, &width, &height, TRUE))
691 /* source x/y might need adjustment if destination x/y was clipped top/left */
692 src_x += dst_x - dst_x_unclipped;
693 src_y += dst_y - dst_y_unclipped;
696 /* skip if rectangle starts outside bitmap */
697 if (src_x >= src_bitmap->width ||
698 src_y >= src_bitmap->height ||
699 dst_x >= dst_bitmap->width ||
700 dst_y >= dst_bitmap->height)
703 /* clip if rectangle overlaps bitmap */
704 if (src_x + width > src_bitmap->width)
705 width = src_bitmap->width - src_x;
706 if (src_y + height > src_bitmap->height)
707 height = src_bitmap->height - src_y;
708 if (dst_x + width > dst_bitmap->width)
709 width = dst_bitmap->width - dst_x;
710 if (dst_y + height > dst_bitmap->height)
711 height = dst_bitmap->height - dst_y;
715 /* !!! 2013-12-11: An "old friend" is back. Same bug in SDL2 2.0.1 !!! */
717 /* !!! 2009-03-30: Fixed by using self-compiled, patched SDL.dll !!! */
718 /* (This bug still exists in the actual (as of 2009-06-15) version 1.2.13,
719 but is already fixed in SVN and should therefore finally be fixed with
720 the next official SDL release, which is probably version 1.2.14.) */
722 /* !!! 2009-03-24: It seems that this problem still exists in 1.2.12 !!! */
723 //#if defined(TARGET_SDL) && defined(PLATFORM_WIN32)
724 #if defined(TARGET_SDL2)
725 if (src_bitmap == dst_bitmap)
727 /* !!! THIS IS A BUG (IN THE SDL LIBRARY?) AND SHOULD BE FIXED !!! */
729 /* needed when blitting directly to same bitmap -- should not be needed with
730 recent SDL libraries, but apparently does not work in 1.2.11 directly */
732 static Bitmap *tmp_bitmap = NULL;
733 static int tmp_bitmap_xsize = 0;
734 static int tmp_bitmap_ysize = 0;
736 /* start with largest static bitmaps for initial bitmap size ... */
737 if (tmp_bitmap_xsize == 0 && tmp_bitmap_ysize == 0)
739 tmp_bitmap_xsize = MAX(gfx.win_xsize, gfx.scrollbuffer_width);
740 tmp_bitmap_ysize = MAX(gfx.win_ysize, gfx.scrollbuffer_height);
743 /* ... and allow for later re-adjustments due to custom artwork bitmaps */
744 if (src_bitmap->width > tmp_bitmap_xsize ||
745 src_bitmap->height > tmp_bitmap_ysize)
747 tmp_bitmap_xsize = MAX(tmp_bitmap_xsize, src_bitmap->width);
748 tmp_bitmap_ysize = MAX(tmp_bitmap_ysize, src_bitmap->height);
750 FreeBitmap(tmp_bitmap);
755 if (tmp_bitmap == NULL)
756 tmp_bitmap = CreateBitmap(tmp_bitmap_xsize, tmp_bitmap_ysize,
759 sysCopyArea(src_bitmap, tmp_bitmap,
760 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
761 sysCopyArea(tmp_bitmap, dst_bitmap,
762 dst_x, dst_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
772 if (dst_x < gfx.sx + gfx.sxsize)
773 printf("::: %d: BlitBitmap(%d, %d, %d, %d)\n",
774 FrameCounter, dst_x, dst_y, width, height);
777 sysCopyArea(src_bitmap, dst_bitmap,
778 src_x, src_y, width, height, dst_x, dst_y, BLIT_OPAQUE);
781 void BlitBitmapTiled(Bitmap *src_bitmap, Bitmap *dst_bitmap,
782 int src_x, int src_y, int src_width, int src_height,
783 int dst_x, int dst_y, int dst_width, int dst_height)
785 int src_xsize = (src_width == 0 ? src_bitmap->width : src_width);
786 int src_ysize = (src_height == 0 ? src_bitmap->height : src_height);
787 int dst_xsize = dst_width;
788 int dst_ysize = dst_height;
789 int src_xsteps = (dst_xsize + src_xsize - 1) / src_xsize;
790 int src_ysteps = (dst_ysize + src_ysize - 1) / src_ysize;
793 for (y = 0; y < src_ysteps; y++)
795 for (x = 0; x < src_xsteps; x++)
797 int draw_x = dst_x + x * src_xsize;
798 int draw_y = dst_y + y * src_ysize;
799 int draw_xsize = MIN(src_xsize, dst_xsize - x * src_xsize);
800 int draw_ysize = MIN(src_ysize, dst_ysize - y * src_ysize);
802 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, draw_xsize, draw_ysize,
808 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
809 int fade_mode, int fade_delay, int post_delay,
810 void (*draw_border_function)(void))
813 /* (use destination bitmap "backbuffer" -- "bitmap_cross" may be undefined) */
814 if (!InClippedRectangle(backbuffer, &x, &y, &width, &height, TRUE))
818 SDLFadeRectangle(bitmap_cross, x, y, width, height,
819 fade_mode, fade_delay, post_delay, draw_border_function);
822 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
825 if (DrawingDeactivated(x, y, width, height))
829 if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
832 /* skip if rectangle starts outside bitmap */
833 if (x >= bitmap->width ||
837 /* clip if rectangle overlaps bitmap */
838 if (x + width > bitmap->width)
839 width = bitmap->width - x;
840 if (y + height > bitmap->height)
841 height = bitmap->height - y;
844 sysFillRectangle(bitmap, x, y, width, height, color);
847 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
849 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
852 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
853 int width, int height)
855 if (DrawingOnBackground(x, y))
856 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
858 ClearRectangle(bitmap, x, y, width, height);
861 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
865 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
869 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
870 int src_x, int src_y, int width, int height,
871 int dst_x, int dst_y)
873 if (DrawingDeactivated(dst_x, dst_y, width, height))
876 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
877 dst_x, dst_y, BLIT_MASKED);
880 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
881 int src_x, int src_y, int width, int height,
882 int dst_x, int dst_y)
884 if (DrawingOnBackground(dst_x, dst_y))
886 /* draw background */
887 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
890 /* draw foreground */
891 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
892 dst_x - src_x, dst_y - src_y);
893 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
897 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
901 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
904 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
907 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
910 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
913 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
914 int to_x, int to_y, Pixel pixel, int line_width)
918 for (x = 0; x < line_width; x++)
920 for (y = 0; y < line_width; y++)
922 int dx = x - line_width / 2;
923 int dy = y - line_width / 2;
925 if ((x == 0 && y == 0) ||
926 (x == 0 && y == line_width - 1) ||
927 (x == line_width - 1 && y == 0) ||
928 (x == line_width - 1 && y == line_width - 1))
932 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
937 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
942 for (i = 0; i < num_points - 1; i++)
943 DrawLine(bitmap, points[i].x, points[i].y,
944 points[i + 1].x, points[i + 1].y, pixel, line_width);
947 SDLDrawLines(bitmap->surface, points, num_points, pixel);
951 Pixel GetPixel(Bitmap *bitmap, int x, int y)
953 if (x < 0 || x >= bitmap->width ||
954 y < 0 || y >= bitmap->height)
957 return SDLGetPixel(bitmap, x, y);
960 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
961 unsigned int color_g, unsigned int color_b)
963 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
966 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
968 unsigned int color_r = (color >> 16) & 0xff;
969 unsigned int color_g = (color >> 8) & 0xff;
970 unsigned int color_b = (color >> 0) & 0xff;
972 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
975 /* execute all pending screen drawing operations */
976 void FlushDisplay(void)
980 /* execute and wait for all pending screen drawing operations */
981 void SyncDisplay(void)
985 void KeyboardAutoRepeatOn(void)
987 #if defined(TARGET_SDL)
988 #if defined(TARGET_SDL2)
989 keyrepeat_status = TRUE;
991 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
992 SDL_DEFAULT_REPEAT_INTERVAL / 2);
993 SDL_EnableUNICODE(1);
997 XAutoRepeatOn(display);
1001 void KeyboardAutoRepeatOff(void)
1003 #if defined(TARGET_SDL)
1004 #if defined(TARGET_SDL2)
1005 keyrepeat_status = FALSE;
1007 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
1008 SDL_EnableUNICODE(0);
1012 XAutoRepeatOff(display);
1016 boolean PointerInWindow(DrawWindow *window)
1018 #if defined(TARGET_SDL)
1026 /* if XQueryPointer() returns False, the pointer
1027 is not on the same screen as the specified window */
1028 return XQueryPointer(display, window->drawable, &root, &child,
1029 &root_x, &root_y, &win_x, &win_y, &mask);
1033 boolean SetVideoMode(boolean fullscreen)
1035 return SDLSetVideoMode(&backbuffer, fullscreen);
1038 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
1040 #if defined(TARGET_SDL)
1041 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
1042 (!fullscreen && video.fullscreen_enabled))
1043 fullscreen = SetVideoMode(fullscreen);
1049 Bitmap *LoadImage(char *filename)
1053 new_bitmap = SDLLoadImage(filename);
1056 new_bitmap->source_filename = getStringCopy(filename);
1061 Bitmap *LoadCustomImage(char *basename)
1063 char *filename = getCustomImageFilename(basename);
1066 if (filename == NULL)
1067 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
1069 if ((new_bitmap = LoadImage(filename)) == NULL)
1070 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
1075 void ReloadCustomImage(Bitmap *bitmap, char *basename)
1077 char *filename = getCustomImageFilename(basename);
1080 if (filename == NULL) /* (should never happen) */
1082 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
1086 if (strEqual(filename, bitmap->source_filename))
1088 /* The old and new image are the same (have the same filename and path).
1089 This usually means that this image does not exist in this graphic set
1090 and a fallback to the existing image is done. */
1095 if ((new_bitmap = LoadImage(filename)) == NULL)
1097 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
1101 if (bitmap->width != new_bitmap->width ||
1102 bitmap->height != new_bitmap->height)
1104 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
1106 FreeBitmap(new_bitmap);
1110 TransferBitmapPointers(new_bitmap, bitmap);
1114 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
1117 // !!! TEST ONLY !!!
1119 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
1120 print_timestamp_time("CreateBitmap");
1122 SDL_Rect src_rect, dst_rect;
1126 src_rect.w = src_bitmap->width - 0;
1127 src_rect.h = src_bitmap->height;
1131 dst_rect.w = dst_bitmap->width;
1132 dst_rect.h = dst_bitmap->height;
1134 SDL_BlitScaled(src_bitmap->surface, &src_rect,
1135 dst_bitmap->surface, &dst_rect);
1136 print_timestamp_time("SDL_BlitScaled");
1140 Bitmap *dst_bitmap = SDLZoomBitmap(src_bitmap, zoom_width, zoom_height);
1146 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
1147 int tile_size, boolean create_small_bitmaps)
1151 Bitmap *tmp_bitmap_final = NULL;
1152 Bitmap *tmp_bitmap_0 = NULL;
1153 Bitmap *tmp_bitmap_1 = NULL;
1154 Bitmap *tmp_bitmap_2 = NULL;
1155 Bitmap *tmp_bitmap_4 = NULL;
1156 Bitmap *tmp_bitmap_8 = NULL;
1157 Bitmap *tmp_bitmap_16 = NULL;
1158 Bitmap *tmp_bitmap_32 = NULL;
1159 int width_final, height_final;
1160 int width_0, height_0;
1161 int width_1, height_1;
1162 int width_2, height_2;
1163 int width_4, height_4;
1164 int width_8, height_8;
1165 int width_16, height_16;
1167 int width_32, height_32;
1169 int old_width, old_height;
1170 int new_width, new_height;
1172 print_timestamp_init("CreateScaledBitmaps");
1174 old_width = old_bitmap->width;
1175 old_height = old_bitmap->height;
1178 /* calculate new image dimensions for final image size */
1179 width_final = old_width * zoom_factor;
1180 height_final = old_height * zoom_factor;
1182 /* get image with final size (this might require scaling up) */
1183 /* ("final" size may result in non-standard tile size image) */
1184 if (zoom_factor != 1)
1185 tmp_bitmap_final = ZoomBitmap(old_bitmap, width_final, height_final);
1187 tmp_bitmap_final = old_bitmap;
1191 /* calculate new image dimensions for final image size */
1192 width_1 = old_width * zoom_factor;
1193 height_1 = old_height * zoom_factor;
1195 /* get image with final size (this might require scaling up) */
1196 /* ("final" size may result in non-standard tile size image) */
1197 if (zoom_factor != 1)
1198 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1200 tmp_bitmap_1 = old_bitmap;
1203 UPDATE_BUSY_STATE();
1205 width_0 = width_1 = width_final;
1206 height_0 = height_1 = height_final;
1208 tmp_bitmap_0 = tmp_bitmap_1 = tmp_bitmap_final;
1211 if (create_small_bitmaps)
1213 /* check if we have a non-gameplay tile size image */
1214 if (tile_size != gfx.game_tile_size)
1216 /* get image with gameplay tile size */
1217 width_0 = width_final * gfx.game_tile_size / tile_size;
1218 height_0 = height_final * gfx.game_tile_size / tile_size;
1220 if (width_0 == old_width)
1221 tmp_bitmap_0 = old_bitmap;
1222 else if (width_0 == width_final)
1223 tmp_bitmap_0 = tmp_bitmap_final;
1227 if (old_width != width_0)
1228 printf("::: %d, %d -> %d, %d\n",
1229 old_width, old_height, width_0, height_0);
1232 tmp_bitmap_0 = ZoomBitmap(old_bitmap, width_0, height_0);
1235 UPDATE_BUSY_STATE();
1238 /* check if we have a non-standard tile size image */
1239 if (tile_size != gfx.standard_tile_size)
1241 /* get image with standard tile size */
1242 width_1 = width_final * gfx.standard_tile_size / tile_size;
1243 height_1 = height_final * gfx.standard_tile_size / tile_size;
1245 if (width_1 == old_width)
1246 tmp_bitmap_1 = old_bitmap;
1247 else if (width_1 == width_final)
1248 tmp_bitmap_1 = tmp_bitmap_final;
1249 else if (width_1 == width_0)
1250 tmp_bitmap_1 = tmp_bitmap_0;
1252 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
1254 UPDATE_BUSY_STATE();
1259 if (create_small_bitmaps)
1261 /* calculate new image dimensions for small images */
1262 width_2 = width_1 / 2;
1263 height_2 = height_1 / 2;
1264 width_4 = width_1 / 4;
1265 height_4 = height_1 / 4;
1266 width_8 = width_1 / 8;
1267 height_8 = height_1 / 8;
1268 width_16 = width_1 / 16;
1269 height_16 = height_1 / 16;
1271 width_32 = width_1 / 32;
1272 height_32 = height_1 / 32;
1276 /* get image with 1/2 of normal size (for use in the level editor) */
1277 if (width_2 == old_width)
1278 tmp_bitmap_2 = old_bitmap;
1280 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_2, height_2);
1282 UPDATE_BUSY_STATE();
1284 /* get image with 1/4 of normal size (for use in the level editor) */
1285 if (width_4 == old_width)
1286 tmp_bitmap_4 = old_bitmap;
1288 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_4, height_4);
1290 UPDATE_BUSY_STATE();
1292 /* get image with 1/8 of normal size (for use on the preview screen) */
1293 if (width_8 == old_width)
1294 tmp_bitmap_8 = old_bitmap;
1296 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_8, height_8);
1298 UPDATE_BUSY_STATE();
1300 /* get image with 1/16 of normal size (for use on the preview screen) */
1301 if (width_16 == old_width)
1302 tmp_bitmap_16 = old_bitmap;
1304 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_16, height_16);
1306 UPDATE_BUSY_STATE();
1308 /* get image with 1/32 of normal size (for use on the preview screen) */
1309 if (width_32 == old_width)
1310 tmp_bitmap_32 = old_bitmap;
1312 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_32, height_32);
1314 UPDATE_BUSY_STATE();
1318 /* get image with 1/2 of normal size (for use in the level editor) */
1319 if (zoom_factor != 2)
1320 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
1322 tmp_bitmap_2 = old_bitmap;
1324 UPDATE_BUSY_STATE();
1326 /* get image with 1/4 of normal size (for use in the level editor) */
1327 if (zoom_factor != 4)
1328 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
1330 tmp_bitmap_4 = old_bitmap;
1332 UPDATE_BUSY_STATE();
1334 /* get image with 1/8 of normal size (for use on the preview screen) */
1335 if (zoom_factor != 8)
1336 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
1338 tmp_bitmap_8 = old_bitmap;
1340 UPDATE_BUSY_STATE();
1342 /* get image with 1/16 of normal size (for use on the preview screen) */
1343 if (zoom_factor != 16)
1344 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
1346 tmp_bitmap_16 = old_bitmap;
1348 UPDATE_BUSY_STATE();
1350 /* get image with 1/32 of normal size (for use on the preview screen) */
1351 if (zoom_factor != 32)
1352 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
1354 tmp_bitmap_32 = old_bitmap;
1356 UPDATE_BUSY_STATE();
1361 /* if image was scaled up, create new clipmask for normal size image */
1362 if (zoom_factor != 1)
1364 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
1366 if (old_bitmap->surface_masked)
1367 SDL_FreeSurface(old_bitmap->surface_masked);
1369 SDL_SetColorKey(tmp_surface_1, SET_TRANSPARENT_PIXEL,
1370 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
1371 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
1372 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1373 SDL_SetColorKey(tmp_surface_1, UNSET_TRANSPARENT_PIXEL, 0);
1377 if (create_small_bitmaps)
1379 new_width = width_1;
1380 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
1383 if (width_0 != width_1)
1385 new_width += width_0;
1386 new_height = MAX(new_height, height_0);
1390 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
1393 if (width_0 != width_1)
1394 BlitBitmap(tmp_bitmap_0, new_bitmap, 0, 0, width_0, height_0, width_1, 0);
1397 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
1398 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
1400 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
1401 width_1 / 2, height_1);
1402 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
1403 3 * width_1 / 4, height_1);
1404 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1405 7 * width_1 / 8, height_1);
1406 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1407 15 * width_1 / 16, height_1);
1409 UPDATE_BUSY_STATE();
1413 new_width = width_1;
1414 new_height = height_1;
1416 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1419 if (create_small_bitmaps)
1421 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1424 if (tmp_bitmap_final != old_bitmap)
1425 FreeBitmap(tmp_bitmap_final);
1427 if (tmp_bitmap_0 != old_bitmap &&
1428 tmp_bitmap_0 != tmp_bitmap_final)
1429 FreeBitmap(tmp_bitmap_0);
1431 if (tmp_bitmap_1 != old_bitmap &&
1432 tmp_bitmap_1 != tmp_bitmap_final &&
1433 tmp_bitmap_1 != tmp_bitmap_0)
1434 FreeBitmap(tmp_bitmap_1);
1436 if (tmp_bitmap_2 != old_bitmap)
1437 FreeBitmap(tmp_bitmap_2);
1439 if (tmp_bitmap_4 != old_bitmap)
1440 FreeBitmap(tmp_bitmap_4);
1442 if (tmp_bitmap_8 != old_bitmap)
1443 FreeBitmap(tmp_bitmap_8);
1445 if (tmp_bitmap_16 != old_bitmap)
1446 FreeBitmap(tmp_bitmap_16);
1448 if (tmp_bitmap_32 != old_bitmap)
1449 FreeBitmap(tmp_bitmap_32);
1453 if (zoom_factor != 1)
1454 FreeBitmap(tmp_bitmap_1);
1456 if (zoom_factor != 2)
1457 FreeBitmap(tmp_bitmap_2);
1459 if (zoom_factor != 4)
1460 FreeBitmap(tmp_bitmap_4);
1462 if (zoom_factor != 8)
1463 FreeBitmap(tmp_bitmap_8);
1465 if (zoom_factor != 16)
1466 FreeBitmap(tmp_bitmap_16);
1468 if (zoom_factor != 32)
1469 FreeBitmap(tmp_bitmap_32);
1473 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1474 #if defined(TARGET_SDL)
1475 swap_bitmap.surface = old_bitmap->surface;
1476 old_bitmap->surface = new_bitmap->surface;
1477 new_bitmap->surface = swap_bitmap.surface;
1479 swap_bitmap.drawable = old_bitmap->drawable;
1480 old_bitmap->drawable = new_bitmap->drawable;
1481 new_bitmap->drawable = swap_bitmap.drawable;
1484 old_bitmap->width = new_bitmap->width;
1485 old_bitmap->height = new_bitmap->height;
1488 /* this replaces all blit masks created when loading -- maybe optimize this */
1490 SDL_Surface *old_surface = old_bitmap->surface;
1492 if (old_bitmap->surface_masked)
1493 SDL_FreeSurface(old_bitmap->surface_masked);
1495 SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL,
1496 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1499 if ((old_bitmap->surface_masked = SDLGetNativeSurface(old_surface)) == NULL)
1500 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1502 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) == NULL)
1503 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1506 SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0);
1510 UPDATE_BUSY_STATE();
1512 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1514 print_timestamp_done("CreateScaledBitmaps");
1517 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor,
1520 CreateScaledBitmaps(old_bitmap, zoom_factor, tile_size, TRUE);
1523 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1525 CreateScaledBitmaps(old_bitmap, zoom_factor, 0, FALSE);
1529 /* ------------------------------------------------------------------------- */
1530 /* mouse pointer functions */
1531 /* ------------------------------------------------------------------------- */
1533 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1535 /* XPM image definitions */
1536 static const char *cursor_image_none[] =
1538 /* width height num_colors chars_per_pixel */
1568 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1569 static const char *cursor_image_dot[] =
1571 /* width height num_colors chars_per_pixel */
1600 static const char **cursor_image_playfield = cursor_image_dot;
1602 /* some people complained about a "white dot" on the screen and thought it
1603 was a graphical error... OK, let's just remove the whole pointer :-) */
1604 static const char **cursor_image_playfield = cursor_image_none;
1607 static const int cursor_bit_order = BIT_ORDER_MSB;
1609 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1611 struct MouseCursorInfo *cursor;
1612 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1613 int header_lines = 4;
1616 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1618 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1621 for (y = 0; y < cursor->width; y++)
1623 for (x = 0; x < cursor->height; x++)
1626 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1631 cursor->data[i] = cursor->mask[i] = 0;
1634 switch (image[header_lines + y][x])
1637 cursor->data[i] |= bit_mask;
1638 cursor->mask[i] |= bit_mask;
1642 cursor->mask[i] |= bit_mask;
1651 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1656 void SetMouseCursor(int mode)
1658 static struct MouseCursorInfo *cursor_none = NULL;
1659 static struct MouseCursorInfo *cursor_playfield = NULL;
1660 struct MouseCursorInfo *cursor_new;
1662 if (cursor_none == NULL)
1663 cursor_none = get_cursor_from_image(cursor_image_none);
1665 if (cursor_playfield == NULL)
1666 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1668 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1669 mode == CURSOR_NONE ? cursor_none :
1670 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1672 SDLSetMouseCursor(cursor_new);
1676 /* ========================================================================= */
1677 /* audio functions */
1678 /* ========================================================================= */
1680 void OpenAudio(void)
1682 /* always start with reliable default values */
1683 audio.sound_available = FALSE;
1684 audio.music_available = FALSE;
1685 audio.loops_available = FALSE;
1687 audio.sound_enabled = FALSE;
1688 audio.sound_deactivated = FALSE;
1690 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1691 audio.mixer_pid = 0;
1692 audio.device_name = NULL;
1693 audio.device_fd = -1;
1695 audio.num_channels = 0;
1696 audio.music_channel = 0;
1697 audio.first_sound_channel = 0;
1699 #if defined(TARGET_SDL)
1704 void CloseAudio(void)
1706 #if defined(TARGET_SDL)
1710 audio.sound_enabled = FALSE;
1713 void SetAudioMode(boolean enabled)
1715 if (!audio.sound_available)
1718 audio.sound_enabled = enabled;
1722 /* ========================================================================= */
1723 /* event functions */
1724 /* ========================================================================= */
1726 void InitEventFilter(EventFilter filter_function)
1728 /* set event filter to filter out certain events */
1729 #if defined(TARGET_SDL)
1730 #if defined(TARGET_SDL2)
1731 SDL_SetEventFilter(filter_function, NULL);
1733 SDL_SetEventFilter(filter_function);
1738 boolean PendingEvent(void)
1740 #if defined(TARGET_SDL)
1741 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1743 return (XPending(display) ? TRUE : FALSE);
1747 void NextEvent(Event *event)
1749 #if defined(TARGET_SDL)
1750 SDLNextEvent(event);
1752 XNextEvent(display, event);
1756 void PeekEvent(Event *event)
1758 #if defined(TARGET_SDL)
1759 #if defined(TARGET_SDL2)
1760 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1762 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1765 XPeekEvent(display, event);
1769 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1771 #if defined(TARGET_SDL)
1772 #if defined(TARGET_SDL2)
1773 /* key up/down events in SDL2 do not return text characters anymore */
1774 return event->keysym.sym;
1778 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1779 (int)event->keysym.unicode,
1780 (int)event->keysym.sym,
1781 (int)SDL_GetModState());
1784 if (with_modifiers &&
1785 event->keysym.unicode > 0x0000 &&
1786 event->keysym.unicode < 0x2000)
1787 return event->keysym.unicode;
1789 return event->keysym.sym;
1795 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1796 (int)XLookupKeysym(event, event->state),
1797 (int)XLookupKeysym(event, 0));
1801 return XLookupKeysym(event, event->state);
1803 return XLookupKeysym(event, 0);
1807 KeyMod HandleKeyModState(Key key, int key_status)
1809 static KeyMod current_modifiers = KMOD_None;
1811 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1813 KeyMod new_modifier = KMOD_None;
1818 new_modifier = KMOD_Shift_L;
1821 new_modifier = KMOD_Shift_R;
1823 case KSYM_Control_L:
1824 new_modifier = KMOD_Control_L;
1826 case KSYM_Control_R:
1827 new_modifier = KMOD_Control_R;
1830 new_modifier = KMOD_Meta_L;
1833 new_modifier = KMOD_Meta_R;
1836 new_modifier = KMOD_Alt_L;
1839 new_modifier = KMOD_Alt_R;
1845 if (key_status == KEY_PRESSED)
1846 current_modifiers |= new_modifier;
1848 current_modifiers &= ~new_modifier;
1851 return current_modifiers;
1854 KeyMod GetKeyModState()
1856 #if defined(TARGET_SDL)
1857 return (KeyMod)SDL_GetModState();
1859 return HandleKeyModState(KSYM_UNDEFINED, 0);
1863 KeyMod GetKeyModStateFromEvents()
1865 /* always use key modifier state as tracked from key events (this is needed
1866 if the modifier key event was injected into the event queue, but the key
1867 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1868 query the keys as held pressed on the keyboard) -- this case is currently
1869 only used to filter out clipboard insert events from "True X-Mouse" tool */
1871 return HandleKeyModState(KSYM_UNDEFINED, 0);
1874 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1876 if (event->type != EVENT_CLIENTMESSAGE)
1879 #if defined(TARGET_SDL)
1880 return TRUE; /* the only possible message here is SDL_QUIT */
1887 /* ========================================================================= */
1888 /* joystick functions */
1889 /* ========================================================================= */
1891 void InitJoysticks()
1895 #if defined(NO_JOYSTICK)
1896 return; /* joysticks generally deactivated by compile-time directive */
1899 /* always start with reliable default values */
1900 joystick.status = JOYSTICK_NOT_AVAILABLE;
1901 for (i = 0; i < MAX_PLAYERS; i++)
1902 joystick.fd[i] = -1; /* joystick device closed */
1904 #if defined(TARGET_SDL)
1909 for (i = 0; i < MAX_PLAYERS; i++)
1910 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1914 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1916 #if defined(TARGET_SDL)
1917 return SDLReadJoystick(nr, x, y, b1, b2);