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;
169 gfx.background_bitmap = NULL;
170 gfx.background_bitmap_mask = REDRAW_NONE;
172 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
173 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
176 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
184 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
192 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
194 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
195 gfx.scrollbuffer_width = scrollbuffer_width;
196 gfx.scrollbuffer_height = scrollbuffer_height;
199 void SetDrawDeactivationMask(int draw_deactivation_mask)
201 gfx.draw_deactivation_mask = draw_deactivation_mask;
204 void SetDrawBackgroundMask(int draw_background_mask)
206 gfx.draw_background_mask = draw_background_mask;
209 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
210 int dest_x, int dest_y, int width, int height)
212 int bitmap_xsize = width;
213 int bitmap_ysize = height;
214 int tile_xsize = tile->width;
215 int tile_ysize = tile->height;
216 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
217 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
220 for (y = 0; y < tile_ysteps; y++)
222 for (x = 0; x < tile_xsteps; x++)
224 int draw_x = dest_x + x * tile_xsize;
225 int draw_y = dest_y + y * tile_ysize;
226 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
227 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
229 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
234 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
236 if (background_bitmap_tile != NULL)
237 gfx.background_bitmap_mask |= mask;
239 gfx.background_bitmap_mask &= ~mask;
241 if (gfx.background_bitmap == NULL)
242 gfx.background_bitmap = CreateBitmap(video.width, video.height,
245 if (background_bitmap_tile == NULL) /* empty background requested */
248 if (mask == REDRAW_FIELD)
249 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
250 gfx.real_sx, gfx.real_sy,
251 gfx.full_sxsize, gfx.full_sysize);
252 else if (mask == REDRAW_DOOR_1)
254 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
256 gfx.dxsize, gfx.dysize);
260 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
262 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
265 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
267 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
271 /* ========================================================================= */
272 /* video functions */
273 /* ========================================================================= */
275 inline static int GetRealDepth(int depth)
277 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
280 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
281 int width, int height, Pixel color)
283 #if defined(TARGET_SDL)
284 SDLFillRectangle(bitmap, x, y, width, height, color);
286 X11FillRectangle(bitmap, x, y, width, height, color);
290 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
291 int src_x, int src_y, int width, int height,
292 int dst_x, int dst_y, int mask_mode)
294 #if defined(TARGET_SDL)
295 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
296 dst_x, dst_y, mask_mode);
298 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
299 dst_x, dst_y, mask_mode);
303 void InitVideoDisplay(void)
305 #if defined(TARGET_SDL)
306 SDLInitVideoDisplay();
308 X11InitVideoDisplay();
312 void CloseVideoDisplay(void)
314 KeyboardAutoRepeatOn();
316 #if defined(TARGET_SDL)
317 SDL_QuitSubSystem(SDL_INIT_VIDEO);
320 XCloseDisplay(display);
324 void InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
325 int width, int height, int depth, boolean fullscreen)
328 video.height = height;
329 video.depth = GetRealDepth(depth);
331 video.fullscreen_available = FULLSCREEN_STATUS;
332 video.fullscreen_enabled = FALSE;
333 video.fullscreen_modes = NULL;
334 video.fullscreen_mode_current = NULL;
336 #if defined(TARGET_SDL)
337 SDLInitVideoBuffer(backbuffer, window, fullscreen);
339 X11InitVideoBuffer(backbuffer, window);
343 Bitmap *CreateBitmapStruct(void)
345 #if defined(TARGET_SDL)
346 return checked_calloc(sizeof(struct SDLSurfaceInfo));
348 return checked_calloc(sizeof(struct X11DrawableInfo));
352 Bitmap *CreateBitmap(int width, int height, int depth)
354 Bitmap *new_bitmap = CreateBitmapStruct();
355 int real_depth = GetRealDepth(depth);
357 #if defined(TARGET_SDL)
358 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
360 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
363 new_bitmap->width = width;
364 new_bitmap->height = height;
369 inline static void FreeBitmapPointers(Bitmap *bitmap)
374 #if defined(TARGET_SDL)
375 SDLFreeBitmapPointers(bitmap);
377 X11FreeBitmapPointers(bitmap);
380 checked_free(bitmap->source_filename);
381 bitmap->source_filename = NULL;
384 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
387 if (src_bitmap == NULL || dst_bitmap == NULL)
390 FreeBitmapPointers(dst_bitmap);
392 *dst_bitmap = *src_bitmap;
395 void FreeBitmap(Bitmap *bitmap)
400 FreeBitmapPointers(bitmap);
405 void CloseWindow(DrawWindow *window)
407 #if defined(TARGET_X11)
408 if (window->drawable)
410 XUnmapWindow(display, window->drawable);
411 XDestroyWindow(display, window->drawable);
414 XFreeGC(display, window->gc);
418 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
421 if (draw_mask == REDRAW_NONE)
424 if (draw_mask & REDRAW_ALL)
427 if ((draw_mask & REDRAW_FIELD) &&
428 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
431 if ((draw_mask & REDRAW_DOOR_1) &&
432 x >= gfx.dx && y < gfx.dy + gfx.dysize)
435 if ((draw_mask & REDRAW_DOOR_2) &&
436 x >= gfx.dx && y >= gfx.vy)
442 boolean DrawingDeactivated(int x, int y, int width, int height)
444 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
447 boolean DrawingOnBackground(int x, int y)
449 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
450 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
453 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
454 int src_x, int src_y, int width, int height,
455 int dst_x, int dst_y)
457 if (DrawingDeactivated(dst_x, dst_y, width, height))
460 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
461 dst_x, dst_y, BLIT_OPAQUE);
464 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
465 int fade_mode, int fade_delay, int post_delay,
466 void (*draw_border_function)(void))
468 #if defined(TARGET_SDL)
469 SDLFadeRectangle(bitmap_cross, x, y, width, height,
470 fade_mode, fade_delay, post_delay, draw_border_function);
472 X11FadeRectangle(bitmap_cross, x, y, width, height,
473 fade_mode, fade_delay, post_delay, draw_border_function);
477 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
480 if (DrawingDeactivated(x, y, width, height))
483 sysFillRectangle(bitmap, x, y, width, height, color);
486 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
488 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
491 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
492 int width, int height)
494 if (DrawingOnBackground(x, y))
495 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
497 ClearRectangle(bitmap, x, y, width, height);
500 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
502 #if defined(TARGET_X11)
505 bitmap->clip_gc = clip_gc;
506 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
511 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
513 #if defined(TARGET_X11)
516 bitmap->clip_gc = clip_gc;
517 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
522 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
523 int src_x, int src_y, int width, int height,
524 int dst_x, int dst_y)
526 if (DrawingDeactivated(dst_x, dst_y, width, height))
529 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
530 dst_x, dst_y, BLIT_MASKED);
533 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
534 int src_x, int src_y, int width, int height,
535 int dst_x, int dst_y)
537 if (DrawingOnBackground(dst_x, dst_y))
539 /* draw background */
540 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
543 /* draw foreground */
544 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
545 dst_x - src_x, dst_y - src_y);
546 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
550 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
554 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
557 #if defined(TARGET_SDL)
558 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
560 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
564 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
567 #if defined(TARGET_SDL)
568 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
570 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
574 #if !defined(TARGET_X11_NATIVE)
575 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
576 int to_x, int to_y, Pixel pixel, int line_width)
580 for (x = 0; x < line_width; x++)
582 for (y = 0; y < line_width; y++)
584 int dx = x - line_width / 2;
585 int dy = y - line_width / 2;
587 if ((x == 0 && y == 0) ||
588 (x == 0 && y == line_width - 1) ||
589 (x == line_width - 1 && y == 0) ||
590 (x == line_width - 1 && y == line_width - 1))
593 #if defined(TARGET_SDL)
595 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
596 #elif defined(TARGET_ALLEGRO)
597 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
598 to_x + dx, to_y + dy, pixel);
605 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
607 #if !defined(TARGET_X11_NATIVE)
611 for (i = 0; i < num_points - 1; i++)
612 DrawLine(bitmap, points[i].x, points[i].y,
613 points[i + 1].x, points[i + 1].y, pixel, line_width);
616 SDLDrawLines(bitmap->surface, points, num_points, pixel);
619 XSetForeground(display, bitmap->line_gc[1], pixel);
620 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
621 (XPoint *)points, num_points, CoordModeOrigin);
625 Pixel GetPixel(Bitmap *bitmap, int x, int y)
627 if (x < 0 || x >= bitmap->width ||
628 y < 0 || y >= bitmap->height)
631 #if defined(TARGET_SDL)
632 return SDLGetPixel(bitmap, x, y);
633 #elif defined(TARGET_ALLEGRO)
634 return AllegroGetPixel(bitmap->drawable, x, y);
636 return X11GetPixel(bitmap, x, y);
640 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
641 unsigned int color_g, unsigned int color_b)
643 #if defined(TARGET_SDL)
644 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
645 #elif defined(TARGET_ALLEGRO)
646 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
648 return X11GetPixelFromRGB(color_r, color_g, color_b);
652 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
654 unsigned int color_r = (color >> 16) & 0xff;
655 unsigned int color_g = (color >> 8) & 0xff;
656 unsigned int color_b = (color >> 0) & 0xff;
658 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
661 /* execute all pending screen drawing operations */
662 void FlushDisplay(void)
669 /* execute and wait for all pending screen drawing operations */
670 void SyncDisplay(void)
673 XSync(display, FALSE);
677 void KeyboardAutoRepeatOn(void)
679 #if defined(TARGET_SDL)
680 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
681 SDL_DEFAULT_REPEAT_INTERVAL / 2);
682 SDL_EnableUNICODE(1);
685 XAutoRepeatOn(display);
689 void KeyboardAutoRepeatOff(void)
691 #if defined(TARGET_SDL)
692 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
693 SDL_EnableUNICODE(0);
696 XAutoRepeatOff(display);
700 boolean PointerInWindow(DrawWindow *window)
702 #if defined(TARGET_SDL)
710 /* if XQueryPointer() returns False, the pointer
711 is not on the same screen as the specified window */
712 return XQueryPointer(display, window->drawable, &root, &child,
713 &root_x, &root_y, &win_x, &win_y, &mask);
717 boolean SetVideoMode(boolean fullscreen)
719 #if defined(TARGET_SDL)
720 return SDLSetVideoMode(&backbuffer, fullscreen);
722 boolean success = TRUE;
724 if (fullscreen && video.fullscreen_available)
726 Error(ERR_WARN, "fullscreen not available in X11 version");
728 /* display error message only once */
729 video.fullscreen_available = FALSE;
738 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
740 #if defined(TARGET_SDL)
741 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
742 (!fullscreen && video.fullscreen_enabled))
743 fullscreen = SetVideoMode(fullscreen);
749 Bitmap *LoadImage(char *filename)
753 #if defined(TARGET_SDL)
754 new_bitmap = SDLLoadImage(filename);
756 new_bitmap = X11LoadImage(filename);
760 new_bitmap->source_filename = getStringCopy(filename);
765 Bitmap *LoadCustomImage(char *basename)
767 char *filename = getCustomImageFilename(basename);
770 if (filename == NULL)
771 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
773 if ((new_bitmap = LoadImage(filename)) == NULL)
774 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
779 void ReloadCustomImage(Bitmap *bitmap, char *basename)
781 char *filename = getCustomImageFilename(basename);
784 if (filename == NULL) /* (should never happen) */
786 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
790 if (strEqual(filename, bitmap->source_filename))
792 /* The old and new image are the same (have the same filename and path).
793 This usually means that this image does not exist in this graphic set
794 and a fallback to the existing image is done. */
799 if ((new_bitmap = LoadImage(filename)) == NULL)
801 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
805 if (bitmap->width != new_bitmap->width ||
806 bitmap->height != new_bitmap->height)
808 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
810 FreeBitmap(new_bitmap);
814 TransferBitmapPointers(new_bitmap, bitmap);
818 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
820 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
822 #if defined(TARGET_SDL)
823 SDLZoomBitmap(src_bitmap, dst_bitmap);
825 X11ZoomBitmap(src_bitmap, dst_bitmap);
831 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
832 boolean create_small_bitmaps)
835 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
836 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
837 int new_width, new_height;
839 /* calculate new image dimensions for normal sized image */
840 width_1 = old_bitmap->width * zoom_factor;
841 height_1 = old_bitmap->height * zoom_factor;
843 /* get image with normal size (this might require scaling up) */
844 if (zoom_factor != 1)
845 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
847 tmp_bitmap_1 = old_bitmap;
849 /* this is only needed to make compilers happy */
850 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
852 if (create_small_bitmaps)
854 /* calculate new image dimensions for small images */
855 width_2 = width_1 / 2;
856 height_2 = height_1 / 2;
857 width_4 = width_1 / 4;
858 height_4 = height_1 / 4;
859 width_8 = width_1 / 8;
860 height_8 = height_1 / 8;
862 /* get image with 1/2 of normal size (for use in the level editor) */
863 if (zoom_factor != 2)
864 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
866 tmp_bitmap_2 = old_bitmap;
868 /* get image with 1/4 of normal size (for use in the level editor) */
869 if (zoom_factor != 4)
870 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
872 tmp_bitmap_4 = old_bitmap;
874 /* get image with 1/8 of normal size (for use on the preview screen) */
875 if (zoom_factor != 8)
876 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
878 tmp_bitmap_8 = old_bitmap;
881 /* if image was scaled up, create new clipmask for normal size image */
882 if (zoom_factor != 1)
884 #if defined(TARGET_X11)
885 if (old_bitmap->clip_mask)
886 XFreePixmap(display, old_bitmap->clip_mask);
888 old_bitmap->clip_mask =
889 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
891 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
893 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
895 if (old_bitmap->surface_masked)
896 SDL_FreeSurface(old_bitmap->surface_masked);
898 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
899 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
900 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
901 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
902 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
906 if (create_small_bitmaps)
909 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
911 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
913 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
914 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
916 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
917 width_1 / 2, height_1);
918 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
919 3 * width_1 / 4, height_1);
924 new_height = height_1;
926 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
929 if (create_small_bitmaps)
931 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
932 if (zoom_factor != 1)
933 FreeBitmap(tmp_bitmap_1);
935 if (zoom_factor != 2)
936 FreeBitmap(tmp_bitmap_2);
938 if (zoom_factor != 4)
939 FreeBitmap(tmp_bitmap_4);
941 if (zoom_factor != 8)
942 FreeBitmap(tmp_bitmap_8);
945 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
946 #if defined(TARGET_SDL)
947 swap_bitmap.surface = old_bitmap->surface;
948 old_bitmap->surface = new_bitmap->surface;
949 new_bitmap->surface = swap_bitmap.surface;
951 swap_bitmap.drawable = old_bitmap->drawable;
952 old_bitmap->drawable = new_bitmap->drawable;
953 new_bitmap->drawable = swap_bitmap.drawable;
956 old_bitmap->width = new_bitmap->width;
957 old_bitmap->height = new_bitmap->height;
959 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
962 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
964 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
967 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
969 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
973 /* ------------------------------------------------------------------------- */
974 /* mouse pointer functions */
975 /* ------------------------------------------------------------------------- */
977 #if !defined(PLATFORM_MSDOS)
979 static const char *cursor_image_playfield[] =
981 /* width height num_colors chars_per_pixel */
990 /* some people complained about a "white dot" on the screen and thought it
991 was a graphical error... OK, let's just remove the whole pointer :-) */
1039 #if defined(TARGET_SDL)
1040 static const int cursor_bit_order = BIT_ORDER_MSB;
1041 #elif defined(TARGET_X11_NATIVE)
1042 static const int cursor_bit_order = BIT_ORDER_LSB;
1045 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1047 struct MouseCursorInfo *cursor;
1048 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1049 int header_lines = 4;
1052 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1054 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1057 for (y = 0; y < cursor->width; y++)
1059 for (x = 0; x < cursor->height; x++)
1062 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1067 cursor->data[i] = cursor->mask[i] = 0;
1070 switch (image[header_lines + y][x])
1073 cursor->data[i] |= bit_mask;
1074 cursor->mask[i] |= bit_mask;
1078 cursor->mask[i] |= bit_mask;
1087 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1091 #endif /* !PLATFORM_MSDOS */
1093 void SetMouseCursor(int mode)
1095 #if !defined(PLATFORM_MSDOS)
1096 static struct MouseCursorInfo *cursor_playfield = NULL;
1098 if (cursor_playfield == NULL)
1099 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1101 #if defined(TARGET_SDL)
1102 SDLSetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1103 #elif defined(TARGET_X11_NATIVE)
1104 X11SetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1110 /* ========================================================================= */
1111 /* audio functions */
1112 /* ========================================================================= */
1114 void OpenAudio(void)
1116 /* always start with reliable default values */
1117 audio.sound_available = FALSE;
1118 audio.music_available = FALSE;
1119 audio.loops_available = FALSE;
1121 audio.sound_enabled = FALSE;
1122 audio.sound_deactivated = FALSE;
1124 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1125 audio.mixer_pid = 0;
1126 audio.device_name = NULL;
1127 audio.device_fd = -1;
1129 audio.num_channels = 0;
1130 audio.music_channel = 0;
1131 audio.first_sound_channel = 0;
1133 #if defined(TARGET_SDL)
1135 #elif defined(PLATFORM_UNIX)
1137 #elif defined(PLATFORM_MSDOS)
1142 void CloseAudio(void)
1144 #if defined(TARGET_SDL)
1146 #elif defined(PLATFORM_UNIX)
1148 #elif defined(PLATFORM_MSDOS)
1152 audio.sound_enabled = FALSE;
1155 void SetAudioMode(boolean enabled)
1157 if (!audio.sound_available)
1160 audio.sound_enabled = enabled;
1164 /* ========================================================================= */
1165 /* event functions */
1166 /* ========================================================================= */
1168 void InitEventFilter(EventFilter filter_function)
1170 #if defined(TARGET_SDL)
1171 /* set event filter to filter out certain events */
1172 SDL_SetEventFilter(filter_function);
1176 boolean PendingEvent(void)
1178 #if defined(TARGET_SDL)
1179 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1181 return (XPending(display) ? TRUE : FALSE);
1185 void NextEvent(Event *event)
1187 #if defined(TARGET_SDL)
1188 SDLNextEvent(event);
1190 XNextEvent(display, event);
1194 void PeekEvent(Event *event)
1196 #if defined(TARGET_SDL)
1197 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1199 XPeekEvent(display, event);
1203 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1205 #if defined(TARGET_SDL)
1208 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1209 (int)event->keysym.unicode,
1210 (int)event->keysym.sym,
1211 (int)SDL_GetModState());
1214 if (with_modifiers &&
1215 event->keysym.unicode > 0x0000 &&
1216 event->keysym.unicode < 0x2000)
1217 return event->keysym.unicode;
1219 return event->keysym.sym;
1224 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1225 (int)XLookupKeysym(event, event->state),
1226 (int)XLookupKeysym(event, 0));
1230 return XLookupKeysym(event, event->state);
1232 return XLookupKeysym(event, 0);
1236 KeyMod HandleKeyModState(Key key, int key_status)
1238 static KeyMod current_modifiers = KMOD_None;
1240 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1242 KeyMod new_modifier = KMOD_None;
1247 new_modifier = KMOD_Shift_L;
1250 new_modifier = KMOD_Shift_R;
1252 case KSYM_Control_L:
1253 new_modifier = KMOD_Control_L;
1255 case KSYM_Control_R:
1256 new_modifier = KMOD_Control_R;
1259 new_modifier = KMOD_Meta_L;
1262 new_modifier = KMOD_Meta_R;
1265 new_modifier = KMOD_Alt_L;
1268 new_modifier = KMOD_Alt_R;
1274 if (key_status == KEY_PRESSED)
1275 current_modifiers |= new_modifier;
1277 current_modifiers &= ~new_modifier;
1280 return current_modifiers;
1283 KeyMod GetKeyModState()
1285 #if defined(TARGET_SDL)
1286 return (KeyMod)SDL_GetModState();
1288 return HandleKeyModState(KSYM_UNDEFINED, 0);
1292 KeyMod GetKeyModStateFromEvents()
1294 /* always use key modifier state as tracked from key events (this is needed
1295 if the modifier key event was injected into the event queue, but the key
1296 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1297 query the keys as held pressed on the keyboard) -- this case is currently
1298 only used to filter out clipboard insert events from "True X-Mouse" tool */
1300 return HandleKeyModState(KSYM_UNDEFINED, 0);
1303 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1305 if (event->type != EVENT_CLIENTMESSAGE)
1308 #if defined(TARGET_SDL)
1309 return TRUE; /* the only possible message here is SDL_QUIT */
1310 #elif defined(PLATFORM_UNIX)
1311 if ((event->window == window->drawable) &&
1312 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1320 /* ========================================================================= */
1321 /* joystick functions */
1322 /* ========================================================================= */
1324 void InitJoysticks()
1328 #if defined(NO_JOYSTICK)
1329 return; /* joysticks generally deactivated by compile-time directive */
1332 /* always start with reliable default values */
1333 joystick.status = JOYSTICK_NOT_AVAILABLE;
1334 for (i = 0; i < MAX_PLAYERS; i++)
1335 joystick.fd[i] = -1; /* joystick device closed */
1337 #if defined(TARGET_SDL)
1339 #elif defined(PLATFORM_UNIX)
1340 UnixInitJoysticks();
1341 #elif defined(PLATFORM_MSDOS)
1342 MSDOSInitJoysticks();
1346 for (i = 0; i < MAX_PLAYERS; i++)
1347 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1351 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1353 #if defined(TARGET_SDL)
1354 return SDLReadJoystick(nr, x, y, b1, b2);
1355 #elif defined(PLATFORM_UNIX)
1356 return UnixReadJoystick(nr, x, y, b1, b2);
1357 #elif defined(PLATFORM_MSDOS)
1358 return MSDOSReadJoystick(nr, x, y, b1, b2);