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) && x < gfx.real_sx + gfx.full_sxsize)
430 if ((draw_mask & REDRAW_DOOR_1) && x >= gfx.dx && y < gfx.dy + gfx.dysize)
433 if ((draw_mask & REDRAW_DOOR_2) && x >= gfx.dx && y >= gfx.vy)
439 boolean DrawingDeactivated(int x, int y, int width, int height)
441 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
444 boolean DrawingOnBackground(int x, int y)
446 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
447 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
450 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
451 int src_x, int src_y, int width, int height,
452 int dst_x, int dst_y)
454 if (DrawingDeactivated(dst_x, dst_y, width, height))
457 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
458 dst_x, dst_y, BLIT_OPAQUE);
461 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
462 int fade_mode, int fade_delay, int post_delay)
464 #if defined(TARGET_SDL)
465 SDLFadeRectangle(bitmap_cross, x, y, width, height,
466 fade_mode, fade_delay, post_delay);
468 X11FadeRectangle(bitmap_cross, x, y, width, height,
469 fade_mode, fade_delay, post_delay);
473 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
476 if (DrawingDeactivated(x, y, width, height))
479 sysFillRectangle(bitmap, x, y, width, height, color);
482 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
484 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
487 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
488 int width, int height)
490 if (DrawingOnBackground(x, y))
491 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
493 ClearRectangle(bitmap, x, y, width, height);
496 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
498 #if defined(TARGET_X11)
501 bitmap->clip_gc = clip_gc;
502 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
507 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
509 #if defined(TARGET_X11)
512 bitmap->clip_gc = clip_gc;
513 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
518 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
519 int src_x, int src_y, int width, int height,
520 int dst_x, int dst_y)
522 if (DrawingDeactivated(dst_x, dst_y, width, height))
525 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
526 dst_x, dst_y, BLIT_MASKED);
529 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
530 int src_x, int src_y, int width, int height,
531 int dst_x, int dst_y)
533 if (DrawingOnBackground(dst_x, dst_y))
535 /* draw background */
536 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
539 /* draw foreground */
540 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
541 dst_x - src_x, dst_y - src_y);
542 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
546 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
550 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
553 #if defined(TARGET_SDL)
554 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
556 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
560 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
563 #if defined(TARGET_SDL)
564 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
566 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
570 #if !defined(TARGET_X11_NATIVE)
571 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
572 int to_x, int to_y, Pixel pixel, int line_width)
576 for (x = 0; x < line_width; x++)
578 for (y = 0; y < line_width; y++)
580 int dx = x - line_width / 2;
581 int dy = y - line_width / 2;
583 if ((x == 0 && y == 0) ||
584 (x == 0 && y == line_width - 1) ||
585 (x == line_width - 1 && y == 0) ||
586 (x == line_width - 1 && y == line_width - 1))
589 #if defined(TARGET_SDL)
591 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
592 #elif defined(TARGET_ALLEGRO)
593 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
594 to_x + dx, to_y + dy, pixel);
601 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
603 #if !defined(TARGET_X11_NATIVE)
607 for (i = 0; i < num_points - 1; i++)
608 DrawLine(bitmap, points[i].x, points[i].y,
609 points[i + 1].x, points[i + 1].y, pixel, line_width);
612 SDLDrawLines(bitmap->surface, points, num_points, pixel);
615 XSetForeground(display, bitmap->line_gc[1], pixel);
616 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
617 (XPoint *)points, num_points, CoordModeOrigin);
621 Pixel GetPixel(Bitmap *bitmap, int x, int y)
623 if (x < 0 || x >= bitmap->width ||
624 y < 0 || y >= bitmap->height)
627 #if defined(TARGET_SDL)
628 return SDLGetPixel(bitmap, x, y);
629 #elif defined(TARGET_ALLEGRO)
630 return AllegroGetPixel(bitmap->drawable, x, y);
632 return X11GetPixel(bitmap, x, y);
636 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
637 unsigned int color_g, unsigned int color_b)
639 #if defined(TARGET_SDL)
640 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
641 #elif defined(TARGET_ALLEGRO)
642 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
644 return X11GetPixelFromRGB(color_r, color_g, color_b);
648 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
650 unsigned int color_r = (color >> 16) & 0xff;
651 unsigned int color_g = (color >> 8) & 0xff;
652 unsigned int color_b = (color >> 0) & 0xff;
654 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
657 /* execute all pending screen drawing operations */
658 void FlushDisplay(void)
665 /* execute and wait for all pending screen drawing operations */
666 void SyncDisplay(void)
669 XSync(display, FALSE);
673 void KeyboardAutoRepeatOn(void)
675 #if defined(TARGET_SDL)
676 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
677 SDL_DEFAULT_REPEAT_INTERVAL / 2);
678 SDL_EnableUNICODE(1);
681 XAutoRepeatOn(display);
685 void KeyboardAutoRepeatOff(void)
687 #if defined(TARGET_SDL)
688 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
689 SDL_EnableUNICODE(0);
692 XAutoRepeatOff(display);
696 boolean PointerInWindow(DrawWindow *window)
698 #if defined(TARGET_SDL)
706 /* if XQueryPointer() returns False, the pointer
707 is not on the same screen as the specified window */
708 return XQueryPointer(display, window->drawable, &root, &child,
709 &root_x, &root_y, &win_x, &win_y, &mask);
713 boolean SetVideoMode(boolean fullscreen)
715 #if defined(TARGET_SDL)
716 return SDLSetVideoMode(&backbuffer, fullscreen);
718 boolean success = TRUE;
720 if (fullscreen && video.fullscreen_available)
722 Error(ERR_WARN, "fullscreen not available in X11 version");
724 /* display error message only once */
725 video.fullscreen_available = FALSE;
734 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
736 #if defined(TARGET_SDL)
737 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
738 (!fullscreen && video.fullscreen_enabled))
739 fullscreen = SetVideoMode(fullscreen);
745 Bitmap *LoadImage(char *filename)
749 #if defined(TARGET_SDL)
750 new_bitmap = SDLLoadImage(filename);
752 new_bitmap = X11LoadImage(filename);
756 new_bitmap->source_filename = getStringCopy(filename);
761 Bitmap *LoadCustomImage(char *basename)
763 char *filename = getCustomImageFilename(basename);
766 if (filename == NULL)
767 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
769 if ((new_bitmap = LoadImage(filename)) == NULL)
770 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
775 void ReloadCustomImage(Bitmap *bitmap, char *basename)
777 char *filename = getCustomImageFilename(basename);
780 if (filename == NULL) /* (should never happen) */
782 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
786 if (strEqual(filename, bitmap->source_filename))
788 /* The old and new image are the same (have the same filename and path).
789 This usually means that this image does not exist in this graphic set
790 and a fallback to the existing image is done. */
795 if ((new_bitmap = LoadImage(filename)) == NULL)
797 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
801 if (bitmap->width != new_bitmap->width ||
802 bitmap->height != new_bitmap->height)
804 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
806 FreeBitmap(new_bitmap);
810 TransferBitmapPointers(new_bitmap, bitmap);
814 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
816 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
818 #if defined(TARGET_SDL)
819 SDLZoomBitmap(src_bitmap, dst_bitmap);
821 X11ZoomBitmap(src_bitmap, dst_bitmap);
827 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
828 boolean create_small_bitmaps)
831 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
832 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
833 int new_width, new_height;
835 /* calculate new image dimensions for normal sized image */
836 width_1 = old_bitmap->width * zoom_factor;
837 height_1 = old_bitmap->height * zoom_factor;
839 /* get image with normal size (this might require scaling up) */
840 if (zoom_factor != 1)
841 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
843 tmp_bitmap_1 = old_bitmap;
845 /* this is only needed to make compilers happy */
846 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
848 if (create_small_bitmaps)
850 /* calculate new image dimensions for small images */
851 width_2 = width_1 / 2;
852 height_2 = height_1 / 2;
853 width_4 = width_1 / 4;
854 height_4 = height_1 / 4;
855 width_8 = width_1 / 8;
856 height_8 = height_1 / 8;
858 /* get image with 1/2 of normal size (for use in the level editor) */
859 if (zoom_factor != 2)
860 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
862 tmp_bitmap_2 = old_bitmap;
864 /* get image with 1/4 of normal size (for use in the level editor) */
865 if (zoom_factor != 4)
866 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
868 tmp_bitmap_4 = old_bitmap;
870 /* get image with 1/8 of normal size (for use on the preview screen) */
871 if (zoom_factor != 8)
872 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
874 tmp_bitmap_8 = old_bitmap;
877 /* if image was scaled up, create new clipmask for normal size image */
878 if (zoom_factor != 1)
880 #if defined(TARGET_X11)
881 if (old_bitmap->clip_mask)
882 XFreePixmap(display, old_bitmap->clip_mask);
884 old_bitmap->clip_mask =
885 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
887 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
889 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
891 if (old_bitmap->surface_masked)
892 SDL_FreeSurface(old_bitmap->surface_masked);
894 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
895 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
896 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
897 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
898 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
902 if (create_small_bitmaps)
905 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
907 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
909 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
910 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
912 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
913 width_1 / 2, height_1);
914 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
915 3 * width_1 / 4, height_1);
920 new_height = height_1;
922 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
925 if (create_small_bitmaps)
927 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
928 if (zoom_factor != 1)
929 FreeBitmap(tmp_bitmap_1);
931 if (zoom_factor != 2)
932 FreeBitmap(tmp_bitmap_2);
934 if (zoom_factor != 4)
935 FreeBitmap(tmp_bitmap_4);
937 if (zoom_factor != 8)
938 FreeBitmap(tmp_bitmap_8);
941 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
942 #if defined(TARGET_SDL)
943 swap_bitmap.surface = old_bitmap->surface;
944 old_bitmap->surface = new_bitmap->surface;
945 new_bitmap->surface = swap_bitmap.surface;
947 swap_bitmap.drawable = old_bitmap->drawable;
948 old_bitmap->drawable = new_bitmap->drawable;
949 new_bitmap->drawable = swap_bitmap.drawable;
952 old_bitmap->width = new_bitmap->width;
953 old_bitmap->height = new_bitmap->height;
955 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
958 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
960 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
963 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
965 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
969 /* ------------------------------------------------------------------------- */
970 /* mouse pointer functions */
971 /* ------------------------------------------------------------------------- */
973 #if !defined(PLATFORM_MSDOS)
975 static const char *cursor_image_playfield[] =
977 /* width height num_colors chars_per_pixel */
986 /* some people complained about a "white dot" on the screen and thought it
987 was a graphical error... OK, let's just remove the whole pointer :-) */
1035 #if defined(TARGET_SDL)
1036 static const int cursor_bit_order = BIT_ORDER_MSB;
1037 #elif defined(TARGET_X11_NATIVE)
1038 static const int cursor_bit_order = BIT_ORDER_LSB;
1041 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1043 struct MouseCursorInfo *cursor;
1044 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1045 int header_lines = 4;
1048 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1050 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1053 for (y = 0; y < cursor->width; y++)
1055 for (x = 0; x < cursor->height; x++)
1058 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1063 cursor->data[i] = cursor->mask[i] = 0;
1066 switch (image[header_lines + y][x])
1069 cursor->data[i] |= bit_mask;
1070 cursor->mask[i] |= bit_mask;
1074 cursor->mask[i] |= bit_mask;
1083 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1087 #endif /* !PLATFORM_MSDOS */
1089 void SetMouseCursor(int mode)
1091 #if !defined(PLATFORM_MSDOS)
1092 static struct MouseCursorInfo *cursor_playfield = NULL;
1094 if (cursor_playfield == NULL)
1095 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1097 #if defined(TARGET_SDL)
1098 SDLSetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1099 #elif defined(TARGET_X11_NATIVE)
1100 X11SetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1106 /* ========================================================================= */
1107 /* audio functions */
1108 /* ========================================================================= */
1110 void OpenAudio(void)
1112 /* always start with reliable default values */
1113 audio.sound_available = FALSE;
1114 audio.music_available = FALSE;
1115 audio.loops_available = FALSE;
1117 audio.sound_enabled = FALSE;
1118 audio.sound_deactivated = FALSE;
1120 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1121 audio.mixer_pid = 0;
1122 audio.device_name = NULL;
1123 audio.device_fd = -1;
1125 audio.num_channels = 0;
1126 audio.music_channel = 0;
1127 audio.first_sound_channel = 0;
1129 #if defined(TARGET_SDL)
1131 #elif defined(PLATFORM_UNIX)
1133 #elif defined(PLATFORM_MSDOS)
1138 void CloseAudio(void)
1140 #if defined(TARGET_SDL)
1142 #elif defined(PLATFORM_UNIX)
1144 #elif defined(PLATFORM_MSDOS)
1148 audio.sound_enabled = FALSE;
1151 void SetAudioMode(boolean enabled)
1153 if (!audio.sound_available)
1156 audio.sound_enabled = enabled;
1160 /* ========================================================================= */
1161 /* event functions */
1162 /* ========================================================================= */
1164 void InitEventFilter(EventFilter filter_function)
1166 #if defined(TARGET_SDL)
1167 /* set event filter to filter out certain events */
1168 SDL_SetEventFilter(filter_function);
1172 boolean PendingEvent(void)
1174 #if defined(TARGET_SDL)
1175 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1177 return (XPending(display) ? TRUE : FALSE);
1181 void NextEvent(Event *event)
1183 #if defined(TARGET_SDL)
1184 SDLNextEvent(event);
1186 XNextEvent(display, event);
1190 void PeekEvent(Event *event)
1192 #if defined(TARGET_SDL)
1193 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1195 XPeekEvent(display, event);
1199 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1201 #if defined(TARGET_SDL)
1204 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1205 (int)event->keysym.unicode,
1206 (int)event->keysym.sym,
1207 (int)SDL_GetModState());
1210 if (with_modifiers &&
1211 event->keysym.unicode > 0x0000 &&
1212 event->keysym.unicode < 0x2000)
1213 return event->keysym.unicode;
1215 return event->keysym.sym;
1220 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1221 (int)XLookupKeysym(event, event->state),
1222 (int)XLookupKeysym(event, 0));
1226 return XLookupKeysym(event, event->state);
1228 return XLookupKeysym(event, 0);
1232 KeyMod HandleKeyModState(Key key, int key_status)
1234 static KeyMod current_modifiers = KMOD_None;
1236 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1238 KeyMod new_modifier = KMOD_None;
1243 new_modifier = KMOD_Shift_L;
1246 new_modifier = KMOD_Shift_R;
1248 case KSYM_Control_L:
1249 new_modifier = KMOD_Control_L;
1251 case KSYM_Control_R:
1252 new_modifier = KMOD_Control_R;
1255 new_modifier = KMOD_Meta_L;
1258 new_modifier = KMOD_Meta_R;
1261 new_modifier = KMOD_Alt_L;
1264 new_modifier = KMOD_Alt_R;
1270 if (key_status == KEY_PRESSED)
1271 current_modifiers |= new_modifier;
1273 current_modifiers &= ~new_modifier;
1276 return current_modifiers;
1279 KeyMod GetKeyModState()
1281 #if defined(TARGET_SDL)
1282 return (KeyMod)SDL_GetModState();
1284 return HandleKeyModState(KSYM_UNDEFINED, 0);
1288 KeyMod GetKeyModStateFromEvents()
1290 /* always use key modifier state as tracked from key events (this is needed
1291 if the modifier key event was injected into the event queue, but the key
1292 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1293 query the keys as held pressed on the keyboard) -- this case is currently
1294 only used to filter out clipboard insert events from "True X-Mouse" tool */
1296 return HandleKeyModState(KSYM_UNDEFINED, 0);
1299 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1301 if (event->type != EVENT_CLIENTMESSAGE)
1304 #if defined(TARGET_SDL)
1305 return TRUE; /* the only possible message here is SDL_QUIT */
1306 #elif defined(PLATFORM_UNIX)
1307 if ((event->window == window->drawable) &&
1308 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1316 /* ========================================================================= */
1317 /* joystick functions */
1318 /* ========================================================================= */
1320 void InitJoysticks()
1324 #if defined(NO_JOYSTICK)
1325 return; /* joysticks generally deactivated by compile-time directive */
1328 /* always start with reliable default values */
1329 joystick.status = JOYSTICK_NOT_AVAILABLE;
1330 for (i = 0; i < MAX_PLAYERS; i++)
1331 joystick.fd[i] = -1; /* joystick device closed */
1333 #if defined(TARGET_SDL)
1335 #elif defined(PLATFORM_UNIX)
1336 UnixInitJoysticks();
1337 #elif defined(PLATFORM_MSDOS)
1338 MSDOSInitJoysticks();
1342 for (i = 0; i < MAX_PLAYERS; i++)
1343 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1347 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1349 #if defined(TARGET_SDL)
1350 return SDLReadJoystick(nr, x, y, b1, b2);
1351 #elif defined(PLATFORM_UNIX)
1352 return UnixReadJoystick(nr, x, y, b1, b2);
1353 #elif defined(PLATFORM_MSDOS)
1354 return MSDOSReadJoystick(nr, x, y, b1, b2);