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)
467 #if defined(TARGET_SDL)
468 SDLFadeRectangle(bitmap_cross, x, y, width, height,
469 fade_mode, fade_delay, post_delay);
471 X11FadeRectangle(bitmap_cross, x, y, width, height,
472 fade_mode, fade_delay, post_delay);
476 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
479 if (DrawingDeactivated(x, y, width, height))
482 sysFillRectangle(bitmap, x, y, width, height, color);
485 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
487 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
490 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
491 int width, int height)
493 if (DrawingOnBackground(x, y))
494 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
496 ClearRectangle(bitmap, x, y, width, height);
499 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
501 #if defined(TARGET_X11)
504 bitmap->clip_gc = clip_gc;
505 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
510 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
512 #if defined(TARGET_X11)
515 bitmap->clip_gc = clip_gc;
516 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
521 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
522 int src_x, int src_y, int width, int height,
523 int dst_x, int dst_y)
525 if (DrawingDeactivated(dst_x, dst_y, width, height))
528 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
529 dst_x, dst_y, BLIT_MASKED);
532 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
533 int src_x, int src_y, int width, int height,
534 int dst_x, int dst_y)
536 if (DrawingOnBackground(dst_x, dst_y))
538 /* draw background */
539 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
542 /* draw foreground */
543 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
544 dst_x - src_x, dst_y - src_y);
545 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
549 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
553 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
556 #if defined(TARGET_SDL)
557 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
559 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
563 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
566 #if defined(TARGET_SDL)
567 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
569 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
573 #if !defined(TARGET_X11_NATIVE)
574 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
575 int to_x, int to_y, Pixel pixel, int line_width)
579 for (x = 0; x < line_width; x++)
581 for (y = 0; y < line_width; y++)
583 int dx = x - line_width / 2;
584 int dy = y - line_width / 2;
586 if ((x == 0 && y == 0) ||
587 (x == 0 && y == line_width - 1) ||
588 (x == line_width - 1 && y == 0) ||
589 (x == line_width - 1 && y == line_width - 1))
592 #if defined(TARGET_SDL)
594 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
595 #elif defined(TARGET_ALLEGRO)
596 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
597 to_x + dx, to_y + dy, pixel);
604 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
606 #if !defined(TARGET_X11_NATIVE)
610 for (i = 0; i < num_points - 1; i++)
611 DrawLine(bitmap, points[i].x, points[i].y,
612 points[i + 1].x, points[i + 1].y, pixel, line_width);
615 SDLDrawLines(bitmap->surface, points, num_points, pixel);
618 XSetForeground(display, bitmap->line_gc[1], pixel);
619 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
620 (XPoint *)points, num_points, CoordModeOrigin);
624 Pixel GetPixel(Bitmap *bitmap, int x, int y)
626 if (x < 0 || x >= bitmap->width ||
627 y < 0 || y >= bitmap->height)
630 #if defined(TARGET_SDL)
631 return SDLGetPixel(bitmap, x, y);
632 #elif defined(TARGET_ALLEGRO)
633 return AllegroGetPixel(bitmap->drawable, x, y);
635 return X11GetPixel(bitmap, x, y);
639 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
640 unsigned int color_g, unsigned int color_b)
642 #if defined(TARGET_SDL)
643 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
644 #elif defined(TARGET_ALLEGRO)
645 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
647 return X11GetPixelFromRGB(color_r, color_g, color_b);
651 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
653 unsigned int color_r = (color >> 16) & 0xff;
654 unsigned int color_g = (color >> 8) & 0xff;
655 unsigned int color_b = (color >> 0) & 0xff;
657 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
660 /* execute all pending screen drawing operations */
661 void FlushDisplay(void)
668 /* execute and wait for all pending screen drawing operations */
669 void SyncDisplay(void)
672 XSync(display, FALSE);
676 void KeyboardAutoRepeatOn(void)
678 #if defined(TARGET_SDL)
679 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
680 SDL_DEFAULT_REPEAT_INTERVAL / 2);
681 SDL_EnableUNICODE(1);
684 XAutoRepeatOn(display);
688 void KeyboardAutoRepeatOff(void)
690 #if defined(TARGET_SDL)
691 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
692 SDL_EnableUNICODE(0);
695 XAutoRepeatOff(display);
699 boolean PointerInWindow(DrawWindow *window)
701 #if defined(TARGET_SDL)
709 /* if XQueryPointer() returns False, the pointer
710 is not on the same screen as the specified window */
711 return XQueryPointer(display, window->drawable, &root, &child,
712 &root_x, &root_y, &win_x, &win_y, &mask);
716 boolean SetVideoMode(boolean fullscreen)
718 #if defined(TARGET_SDL)
719 return SDLSetVideoMode(&backbuffer, fullscreen);
721 boolean success = TRUE;
723 if (fullscreen && video.fullscreen_available)
725 Error(ERR_WARN, "fullscreen not available in X11 version");
727 /* display error message only once */
728 video.fullscreen_available = FALSE;
737 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
739 #if defined(TARGET_SDL)
740 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
741 (!fullscreen && video.fullscreen_enabled))
742 fullscreen = SetVideoMode(fullscreen);
748 Bitmap *LoadImage(char *filename)
752 #if defined(TARGET_SDL)
753 new_bitmap = SDLLoadImage(filename);
755 new_bitmap = X11LoadImage(filename);
759 new_bitmap->source_filename = getStringCopy(filename);
764 Bitmap *LoadCustomImage(char *basename)
766 char *filename = getCustomImageFilename(basename);
769 if (filename == NULL)
770 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
772 if ((new_bitmap = LoadImage(filename)) == NULL)
773 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
778 void ReloadCustomImage(Bitmap *bitmap, char *basename)
780 char *filename = getCustomImageFilename(basename);
783 if (filename == NULL) /* (should never happen) */
785 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
789 if (strEqual(filename, bitmap->source_filename))
791 /* The old and new image are the same (have the same filename and path).
792 This usually means that this image does not exist in this graphic set
793 and a fallback to the existing image is done. */
798 if ((new_bitmap = LoadImage(filename)) == NULL)
800 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
804 if (bitmap->width != new_bitmap->width ||
805 bitmap->height != new_bitmap->height)
807 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
809 FreeBitmap(new_bitmap);
813 TransferBitmapPointers(new_bitmap, bitmap);
817 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
819 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
821 #if defined(TARGET_SDL)
822 SDLZoomBitmap(src_bitmap, dst_bitmap);
824 X11ZoomBitmap(src_bitmap, dst_bitmap);
830 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
831 boolean create_small_bitmaps)
834 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
835 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
836 int new_width, new_height;
838 /* calculate new image dimensions for normal sized image */
839 width_1 = old_bitmap->width * zoom_factor;
840 height_1 = old_bitmap->height * zoom_factor;
842 /* get image with normal size (this might require scaling up) */
843 if (zoom_factor != 1)
844 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
846 tmp_bitmap_1 = old_bitmap;
848 /* this is only needed to make compilers happy */
849 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
851 if (create_small_bitmaps)
853 /* calculate new image dimensions for small images */
854 width_2 = width_1 / 2;
855 height_2 = height_1 / 2;
856 width_4 = width_1 / 4;
857 height_4 = height_1 / 4;
858 width_8 = width_1 / 8;
859 height_8 = height_1 / 8;
861 /* get image with 1/2 of normal size (for use in the level editor) */
862 if (zoom_factor != 2)
863 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
865 tmp_bitmap_2 = old_bitmap;
867 /* get image with 1/4 of normal size (for use in the level editor) */
868 if (zoom_factor != 4)
869 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
871 tmp_bitmap_4 = old_bitmap;
873 /* get image with 1/8 of normal size (for use on the preview screen) */
874 if (zoom_factor != 8)
875 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
877 tmp_bitmap_8 = old_bitmap;
880 /* if image was scaled up, create new clipmask for normal size image */
881 if (zoom_factor != 1)
883 #if defined(TARGET_X11)
884 if (old_bitmap->clip_mask)
885 XFreePixmap(display, old_bitmap->clip_mask);
887 old_bitmap->clip_mask =
888 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
890 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
892 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
894 if (old_bitmap->surface_masked)
895 SDL_FreeSurface(old_bitmap->surface_masked);
897 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
898 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
899 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
900 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
901 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
905 if (create_small_bitmaps)
908 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
910 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
912 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
913 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
915 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
916 width_1 / 2, height_1);
917 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
918 3 * width_1 / 4, height_1);
923 new_height = height_1;
925 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
928 if (create_small_bitmaps)
930 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
931 if (zoom_factor != 1)
932 FreeBitmap(tmp_bitmap_1);
934 if (zoom_factor != 2)
935 FreeBitmap(tmp_bitmap_2);
937 if (zoom_factor != 4)
938 FreeBitmap(tmp_bitmap_4);
940 if (zoom_factor != 8)
941 FreeBitmap(tmp_bitmap_8);
944 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
945 #if defined(TARGET_SDL)
946 swap_bitmap.surface = old_bitmap->surface;
947 old_bitmap->surface = new_bitmap->surface;
948 new_bitmap->surface = swap_bitmap.surface;
950 swap_bitmap.drawable = old_bitmap->drawable;
951 old_bitmap->drawable = new_bitmap->drawable;
952 new_bitmap->drawable = swap_bitmap.drawable;
955 old_bitmap->width = new_bitmap->width;
956 old_bitmap->height = new_bitmap->height;
958 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
961 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
963 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
966 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
968 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
972 /* ------------------------------------------------------------------------- */
973 /* mouse pointer functions */
974 /* ------------------------------------------------------------------------- */
976 #if !defined(PLATFORM_MSDOS)
978 static const char *cursor_image_playfield[] =
980 /* width height num_colors chars_per_pixel */
989 /* some people complained about a "white dot" on the screen and thought it
990 was a graphical error... OK, let's just remove the whole pointer :-) */
1038 #if defined(TARGET_SDL)
1039 static const int cursor_bit_order = BIT_ORDER_MSB;
1040 #elif defined(TARGET_X11_NATIVE)
1041 static const int cursor_bit_order = BIT_ORDER_LSB;
1044 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1046 struct MouseCursorInfo *cursor;
1047 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1048 int header_lines = 4;
1051 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1053 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1056 for (y = 0; y < cursor->width; y++)
1058 for (x = 0; x < cursor->height; x++)
1061 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1066 cursor->data[i] = cursor->mask[i] = 0;
1069 switch (image[header_lines + y][x])
1072 cursor->data[i] |= bit_mask;
1073 cursor->mask[i] |= bit_mask;
1077 cursor->mask[i] |= bit_mask;
1086 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1090 #endif /* !PLATFORM_MSDOS */
1092 void SetMouseCursor(int mode)
1094 #if !defined(PLATFORM_MSDOS)
1095 static struct MouseCursorInfo *cursor_playfield = NULL;
1097 if (cursor_playfield == NULL)
1098 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1100 #if defined(TARGET_SDL)
1101 SDLSetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1102 #elif defined(TARGET_X11_NATIVE)
1103 X11SetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1109 /* ========================================================================= */
1110 /* audio functions */
1111 /* ========================================================================= */
1113 void OpenAudio(void)
1115 /* always start with reliable default values */
1116 audio.sound_available = FALSE;
1117 audio.music_available = FALSE;
1118 audio.loops_available = FALSE;
1120 audio.sound_enabled = FALSE;
1121 audio.sound_deactivated = FALSE;
1123 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1124 audio.mixer_pid = 0;
1125 audio.device_name = NULL;
1126 audio.device_fd = -1;
1128 audio.num_channels = 0;
1129 audio.music_channel = 0;
1130 audio.first_sound_channel = 0;
1132 #if defined(TARGET_SDL)
1134 #elif defined(PLATFORM_UNIX)
1136 #elif defined(PLATFORM_MSDOS)
1141 void CloseAudio(void)
1143 #if defined(TARGET_SDL)
1145 #elif defined(PLATFORM_UNIX)
1147 #elif defined(PLATFORM_MSDOS)
1151 audio.sound_enabled = FALSE;
1154 void SetAudioMode(boolean enabled)
1156 if (!audio.sound_available)
1159 audio.sound_enabled = enabled;
1163 /* ========================================================================= */
1164 /* event functions */
1165 /* ========================================================================= */
1167 void InitEventFilter(EventFilter filter_function)
1169 #if defined(TARGET_SDL)
1170 /* set event filter to filter out certain events */
1171 SDL_SetEventFilter(filter_function);
1175 boolean PendingEvent(void)
1177 #if defined(TARGET_SDL)
1178 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1180 return (XPending(display) ? TRUE : FALSE);
1184 void NextEvent(Event *event)
1186 #if defined(TARGET_SDL)
1187 SDLNextEvent(event);
1189 XNextEvent(display, event);
1193 void PeekEvent(Event *event)
1195 #if defined(TARGET_SDL)
1196 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1198 XPeekEvent(display, event);
1202 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1204 #if defined(TARGET_SDL)
1207 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1208 (int)event->keysym.unicode,
1209 (int)event->keysym.sym,
1210 (int)SDL_GetModState());
1213 if (with_modifiers &&
1214 event->keysym.unicode > 0x0000 &&
1215 event->keysym.unicode < 0x2000)
1216 return event->keysym.unicode;
1218 return event->keysym.sym;
1223 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1224 (int)XLookupKeysym(event, event->state),
1225 (int)XLookupKeysym(event, 0));
1229 return XLookupKeysym(event, event->state);
1231 return XLookupKeysym(event, 0);
1235 KeyMod HandleKeyModState(Key key, int key_status)
1237 static KeyMod current_modifiers = KMOD_None;
1239 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1241 KeyMod new_modifier = KMOD_None;
1246 new_modifier = KMOD_Shift_L;
1249 new_modifier = KMOD_Shift_R;
1251 case KSYM_Control_L:
1252 new_modifier = KMOD_Control_L;
1254 case KSYM_Control_R:
1255 new_modifier = KMOD_Control_R;
1258 new_modifier = KMOD_Meta_L;
1261 new_modifier = KMOD_Meta_R;
1264 new_modifier = KMOD_Alt_L;
1267 new_modifier = KMOD_Alt_R;
1273 if (key_status == KEY_PRESSED)
1274 current_modifiers |= new_modifier;
1276 current_modifiers &= ~new_modifier;
1279 return current_modifiers;
1282 KeyMod GetKeyModState()
1284 #if defined(TARGET_SDL)
1285 return (KeyMod)SDL_GetModState();
1287 return HandleKeyModState(KSYM_UNDEFINED, 0);
1291 KeyMod GetKeyModStateFromEvents()
1293 /* always use key modifier state as tracked from key events (this is needed
1294 if the modifier key event was injected into the event queue, but the key
1295 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1296 query the keys as held pressed on the keyboard) -- this case is currently
1297 only used to filter out clipboard insert events from "True X-Mouse" tool */
1299 return HandleKeyModState(KSYM_UNDEFINED, 0);
1302 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1304 if (event->type != EVENT_CLIENTMESSAGE)
1307 #if defined(TARGET_SDL)
1308 return TRUE; /* the only possible message here is SDL_QUIT */
1309 #elif defined(PLATFORM_UNIX)
1310 if ((event->window == window->drawable) &&
1311 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1319 /* ========================================================================= */
1320 /* joystick functions */
1321 /* ========================================================================= */
1323 void InitJoysticks()
1327 #if defined(NO_JOYSTICK)
1328 return; /* joysticks generally deactivated by compile-time directive */
1331 /* always start with reliable default values */
1332 joystick.status = JOYSTICK_NOT_AVAILABLE;
1333 for (i = 0; i < MAX_PLAYERS; i++)
1334 joystick.fd[i] = -1; /* joystick device closed */
1336 #if defined(TARGET_SDL)
1338 #elif defined(PLATFORM_UNIX)
1339 UnixInitJoysticks();
1340 #elif defined(PLATFORM_MSDOS)
1341 MSDOSInitJoysticks();
1345 for (i = 0; i < MAX_PLAYERS; i++)
1346 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1350 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1352 #if defined(TARGET_SDL)
1353 return SDLReadJoystick(nr, x, y, b1, b2);
1354 #elif defined(PLATFORM_UNIX)
1355 return UnixReadJoystick(nr, x, y, b1, b2);
1356 #elif defined(PLATFORM_MSDOS)
1357 return MSDOSReadJoystick(nr, x, y, b1, b2);