1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2002 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);
330 video.fullscreen_available = FULLSCREEN_STATUS;
331 video.fullscreen_enabled = FALSE;
332 video.fullscreen_modes = NULL;
333 video.fullscreen_mode_current = NULL;
335 #if defined(TARGET_SDL)
336 SDLInitVideoBuffer(backbuffer, window, fullscreen);
338 X11InitVideoBuffer(backbuffer, window);
342 Bitmap *CreateBitmapStruct(void)
344 #if defined(TARGET_SDL)
345 return checked_calloc(sizeof(struct SDLSurfaceInfo));
347 return checked_calloc(sizeof(struct X11DrawableInfo));
351 Bitmap *CreateBitmap(int width, int height, int depth)
353 Bitmap *new_bitmap = CreateBitmapStruct();
354 int real_depth = GetRealDepth(depth);
356 #if defined(TARGET_SDL)
357 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
359 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
362 new_bitmap->width = width;
363 new_bitmap->height = height;
368 inline static void FreeBitmapPointers(Bitmap *bitmap)
373 #if defined(TARGET_SDL)
374 SDLFreeBitmapPointers(bitmap);
376 X11FreeBitmapPointers(bitmap);
379 checked_free(bitmap->source_filename);
380 bitmap->source_filename = NULL;
383 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
386 if (src_bitmap == NULL || dst_bitmap == NULL)
389 FreeBitmapPointers(dst_bitmap);
391 *dst_bitmap = *src_bitmap;
394 void FreeBitmap(Bitmap *bitmap)
399 FreeBitmapPointers(bitmap);
404 void CloseWindow(DrawWindow *window)
406 #if defined(TARGET_X11)
407 if (window->drawable)
409 XUnmapWindow(display, window->drawable);
410 XDestroyWindow(display, window->drawable);
413 XFreeGC(display, window->gc);
417 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
420 if (draw_mask == REDRAW_NONE)
423 if (draw_mask & REDRAW_ALL)
426 if ((draw_mask & REDRAW_FIELD) && x < gfx.real_sx + gfx.full_sxsize)
429 if ((draw_mask & REDRAW_DOOR_1) && x >= gfx.dx && y < gfx.dy + gfx.dysize)
432 if ((draw_mask & REDRAW_DOOR_2) && x >= gfx.dx && y >= gfx.vy)
438 boolean DrawingDeactivated(int x, int y, int width, int height)
440 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
443 boolean DrawingOnBackground(int x, int y)
445 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
446 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
449 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
450 int src_x, int src_y, int width, int height,
451 int dst_x, int dst_y)
453 if (DrawingDeactivated(dst_x, dst_y, width, height))
456 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
457 dst_x, dst_y, BLIT_OPAQUE);
460 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
461 int fade_mode, int fade_delay, int post_delay)
463 #if defined(TARGET_SDL)
464 SDLFadeRectangle(bitmap_cross, x, y, width, height,
465 fade_mode, fade_delay, post_delay);
467 X11FadeRectangle(bitmap_cross, x, y, width, height,
468 fade_mode, fade_delay, post_delay);
472 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
475 if (DrawingDeactivated(x, y, width, height))
478 sysFillRectangle(bitmap, x, y, width, height, color);
481 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
483 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
486 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
487 int width, int height)
489 if (DrawingOnBackground(x, y))
490 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
492 ClearRectangle(bitmap, x, y, width, height);
495 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
497 #if defined(TARGET_X11)
500 bitmap->clip_gc = clip_gc;
501 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
506 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
508 #if defined(TARGET_X11)
511 bitmap->clip_gc = clip_gc;
512 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
517 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
518 int src_x, int src_y, int width, int height,
519 int dst_x, int dst_y)
521 if (DrawingDeactivated(dst_x, dst_y, width, height))
524 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
525 dst_x, dst_y, BLIT_MASKED);
528 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
529 int src_x, int src_y, int width, int height,
530 int dst_x, int dst_y)
532 if (DrawingOnBackground(dst_x, dst_y))
534 /* draw background */
535 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
538 /* draw foreground */
539 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
540 dst_x - src_x, dst_y - src_y);
541 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
545 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
549 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
552 #if defined(TARGET_SDL)
553 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
555 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
559 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
562 #if defined(TARGET_SDL)
563 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
565 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
569 #if !defined(TARGET_X11_NATIVE)
570 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
571 int to_x, int to_y, Pixel pixel, int line_width)
575 for (x = 0; x < line_width; x++)
577 for (y = 0; y < line_width; y++)
579 int dx = x - line_width / 2;
580 int dy = y - line_width / 2;
582 if ((x == 0 && y == 0) ||
583 (x == 0 && y == line_width - 1) ||
584 (x == line_width - 1 && y == 0) ||
585 (x == line_width - 1 && y == line_width - 1))
588 #if defined(TARGET_SDL)
590 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
591 #elif defined(TARGET_ALLEGRO)
592 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
593 to_x + dx, to_y + dy, pixel);
600 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
602 #if !defined(TARGET_X11_NATIVE)
606 for (i = 0; i < num_points - 1; i++)
607 DrawLine(bitmap, points[i].x, points[i].y,
608 points[i + 1].x, points[i + 1].y, pixel, line_width);
611 SDLDrawLines(bitmap->surface, points, num_points, pixel);
614 XSetForeground(display, bitmap->line_gc[1], pixel);
615 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
616 (XPoint *)points, num_points, CoordModeOrigin);
620 Pixel GetPixel(Bitmap *bitmap, int x, int y)
622 if (x < 0 || x >= bitmap->width ||
623 y < 0 || y >= bitmap->height)
626 #if defined(TARGET_SDL)
627 return SDLGetPixel(bitmap, x, y);
628 #elif defined(TARGET_ALLEGRO)
629 return AllegroGetPixel(bitmap->drawable, x, y);
631 return X11GetPixel(bitmap, x, y);
635 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
636 unsigned int color_g, unsigned int color_b)
638 #if defined(TARGET_SDL)
639 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
640 #elif defined(TARGET_ALLEGRO)
641 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
643 return X11GetPixelFromRGB(color_r, color_g, color_b);
647 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
649 unsigned int color_r = (color >> 16) & 0xff;
650 unsigned int color_g = (color >> 8) & 0xff;
651 unsigned int color_b = (color >> 0) & 0xff;
653 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
656 /* execute all pending screen drawing operations */
657 void FlushDisplay(void)
664 /* execute and wait for all pending screen drawing operations */
665 void SyncDisplay(void)
668 XSync(display, FALSE);
672 void KeyboardAutoRepeatOn(void)
674 #if defined(TARGET_SDL)
675 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
676 SDL_DEFAULT_REPEAT_INTERVAL / 2);
677 SDL_EnableUNICODE(1);
680 XAutoRepeatOn(display);
684 void KeyboardAutoRepeatOff(void)
686 #if defined(TARGET_SDL)
687 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
688 SDL_EnableUNICODE(0);
691 XAutoRepeatOff(display);
695 boolean PointerInWindow(DrawWindow *window)
697 #if defined(TARGET_SDL)
705 /* if XQueryPointer() returns False, the pointer
706 is not on the same screen as the specified window */
707 return XQueryPointer(display, window->drawable, &root, &child,
708 &root_x, &root_y, &win_x, &win_y, &mask);
712 boolean SetVideoMode(boolean fullscreen)
714 #if defined(TARGET_SDL)
715 return SDLSetVideoMode(&backbuffer, fullscreen);
717 boolean success = TRUE;
719 if (fullscreen && video.fullscreen_available)
721 Error(ERR_WARN, "fullscreen not available in X11 version");
723 /* display error message only once */
724 video.fullscreen_available = FALSE;
733 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
735 #if defined(TARGET_SDL)
736 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
737 (!fullscreen && video.fullscreen_enabled))
738 fullscreen = SetVideoMode(fullscreen);
744 Bitmap *LoadImage(char *filename)
748 #if defined(TARGET_SDL)
749 new_bitmap = SDLLoadImage(filename);
751 new_bitmap = X11LoadImage(filename);
755 new_bitmap->source_filename = getStringCopy(filename);
760 Bitmap *LoadCustomImage(char *basename)
762 char *filename = getCustomImageFilename(basename);
765 if (filename == NULL)
766 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
768 if ((new_bitmap = LoadImage(filename)) == NULL)
769 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
774 void ReloadCustomImage(Bitmap *bitmap, char *basename)
776 char *filename = getCustomImageFilename(basename);
779 if (filename == NULL) /* (should never happen) */
781 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
785 if (strEqual(filename, bitmap->source_filename))
787 /* The old and new image are the same (have the same filename and path).
788 This usually means that this image does not exist in this graphic set
789 and a fallback to the existing image is done. */
794 if ((new_bitmap = LoadImage(filename)) == NULL)
796 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
800 if (bitmap->width != new_bitmap->width ||
801 bitmap->height != new_bitmap->height)
803 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
805 FreeBitmap(new_bitmap);
809 TransferBitmapPointers(new_bitmap, bitmap);
813 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
815 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
817 #if defined(TARGET_SDL)
818 SDLZoomBitmap(src_bitmap, dst_bitmap);
820 X11ZoomBitmap(src_bitmap, dst_bitmap);
826 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
827 boolean create_small_bitmaps)
830 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
831 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
832 int new_width, new_height;
834 /* calculate new image dimensions for normal sized image */
835 width_1 = old_bitmap->width * zoom_factor;
836 height_1 = old_bitmap->height * zoom_factor;
838 /* get image with normal size (this might require scaling up) */
839 if (zoom_factor != 1)
840 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
842 tmp_bitmap_1 = old_bitmap;
844 /* this is only needed to make compilers happy */
845 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
847 if (create_small_bitmaps)
849 /* calculate new image dimensions for small images */
850 width_2 = width_1 / 2;
851 height_2 = height_1 / 2;
852 width_4 = width_1 / 4;
853 height_4 = height_1 / 4;
854 width_8 = width_1 / 8;
855 height_8 = height_1 / 8;
857 /* get image with 1/2 of normal size (for use in the level editor) */
858 if (zoom_factor != 2)
859 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
861 tmp_bitmap_2 = old_bitmap;
863 /* get image with 1/4 of normal size (for use in the level editor) */
864 if (zoom_factor != 4)
865 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
867 tmp_bitmap_4 = old_bitmap;
869 /* get image with 1/8 of normal size (for use on the preview screen) */
870 if (zoom_factor != 8)
871 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
873 tmp_bitmap_8 = old_bitmap;
876 /* if image was scaled up, create new clipmask for normal size image */
877 if (zoom_factor != 1)
879 #if defined(TARGET_X11)
880 if (old_bitmap->clip_mask)
881 XFreePixmap(display, old_bitmap->clip_mask);
883 old_bitmap->clip_mask =
884 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
886 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
888 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
890 if (old_bitmap->surface_masked)
891 SDL_FreeSurface(old_bitmap->surface_masked);
893 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
894 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
895 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
896 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
897 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
901 if (create_small_bitmaps)
904 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
906 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
908 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
909 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
911 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
912 width_1 / 2, height_1);
913 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
914 3 * width_1 / 4, height_1);
919 new_height = height_1;
921 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
924 if (create_small_bitmaps)
926 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
927 if (zoom_factor != 1)
928 FreeBitmap(tmp_bitmap_1);
930 if (zoom_factor != 2)
931 FreeBitmap(tmp_bitmap_2);
933 if (zoom_factor != 4)
934 FreeBitmap(tmp_bitmap_4);
936 if (zoom_factor != 8)
937 FreeBitmap(tmp_bitmap_8);
940 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
941 #if defined(TARGET_SDL)
942 swap_bitmap.surface = old_bitmap->surface;
943 old_bitmap->surface = new_bitmap->surface;
944 new_bitmap->surface = swap_bitmap.surface;
946 swap_bitmap.drawable = old_bitmap->drawable;
947 old_bitmap->drawable = new_bitmap->drawable;
948 new_bitmap->drawable = swap_bitmap.drawable;
951 old_bitmap->width = new_bitmap->width;
952 old_bitmap->height = new_bitmap->height;
954 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
957 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
959 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
962 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
964 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
968 /* ------------------------------------------------------------------------- */
969 /* mouse pointer functions */
970 /* ------------------------------------------------------------------------- */
972 #if !defined(PLATFORM_MSDOS)
974 static const char *cursor_image_playfield[] =
976 /* width height num_colors chars_per_pixel */
985 /* some people complained about a "white dot" on the screen and thought it
986 was a graphical error... OK, let's just remove the whole pointer :-) */
1034 #if defined(TARGET_SDL)
1035 static const int cursor_bit_order = BIT_ORDER_MSB;
1036 #elif defined(TARGET_X11_NATIVE)
1037 static const int cursor_bit_order = BIT_ORDER_LSB;
1040 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1042 struct MouseCursorInfo *cursor;
1043 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1044 int header_lines = 4;
1047 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1049 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1052 for (y = 0; y < cursor->width; y++)
1054 for (x = 0; x < cursor->height; x++)
1057 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1062 cursor->data[i] = cursor->mask[i] = 0;
1065 switch (image[header_lines + y][x])
1068 cursor->data[i] |= bit_mask;
1069 cursor->mask[i] |= bit_mask;
1073 cursor->mask[i] |= bit_mask;
1082 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1086 #endif /* !PLATFORM_MSDOS */
1088 void SetMouseCursor(int mode)
1090 #if !defined(PLATFORM_MSDOS)
1091 static struct MouseCursorInfo *cursor_playfield = NULL;
1093 if (cursor_playfield == NULL)
1094 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1096 #if defined(TARGET_SDL)
1097 SDLSetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1098 #elif defined(TARGET_X11_NATIVE)
1099 X11SetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1105 /* ========================================================================= */
1106 /* audio functions */
1107 /* ========================================================================= */
1109 void OpenAudio(void)
1111 /* always start with reliable default values */
1112 audio.sound_available = FALSE;
1113 audio.music_available = FALSE;
1114 audio.loops_available = FALSE;
1116 audio.sound_enabled = FALSE;
1117 audio.sound_deactivated = FALSE;
1119 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1120 audio.mixer_pid = 0;
1121 audio.device_name = NULL;
1122 audio.device_fd = -1;
1124 audio.num_channels = 0;
1125 audio.music_channel = 0;
1126 audio.first_sound_channel = 0;
1128 #if defined(TARGET_SDL)
1130 #elif defined(PLATFORM_UNIX)
1132 #elif defined(PLATFORM_MSDOS)
1137 void CloseAudio(void)
1139 #if defined(TARGET_SDL)
1141 #elif defined(PLATFORM_UNIX)
1143 #elif defined(PLATFORM_MSDOS)
1147 audio.sound_enabled = FALSE;
1150 void SetAudioMode(boolean enabled)
1152 if (!audio.sound_available)
1155 audio.sound_enabled = enabled;
1159 /* ========================================================================= */
1160 /* event functions */
1161 /* ========================================================================= */
1163 void InitEventFilter(EventFilter filter_function)
1165 #if defined(TARGET_SDL)
1166 /* set event filter to filter out certain events */
1167 SDL_SetEventFilter(filter_function);
1171 boolean PendingEvent(void)
1173 #if defined(TARGET_SDL)
1174 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1176 return (XPending(display) ? TRUE : FALSE);
1180 void NextEvent(Event *event)
1182 #if defined(TARGET_SDL)
1183 SDLNextEvent(event);
1185 XNextEvent(display, event);
1189 void PeekEvent(Event *event)
1191 #if defined(TARGET_SDL)
1192 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1194 XPeekEvent(display, event);
1198 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1200 #if defined(TARGET_SDL)
1203 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1204 (int)event->keysym.unicode,
1205 (int)event->keysym.sym,
1206 (int)SDL_GetModState());
1209 if (with_modifiers &&
1210 event->keysym.unicode > 0x0000 &&
1211 event->keysym.unicode < 0x2000)
1212 return event->keysym.unicode;
1214 return event->keysym.sym;
1219 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1220 (int)XLookupKeysym(event, event->state),
1221 (int)XLookupKeysym(event, 0));
1225 return XLookupKeysym(event, event->state);
1227 return XLookupKeysym(event, 0);
1231 KeyMod HandleKeyModState(Key key, int key_status)
1233 static KeyMod current_modifiers = KMOD_None;
1235 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1237 KeyMod new_modifier = KMOD_None;
1242 new_modifier = KMOD_Shift_L;
1245 new_modifier = KMOD_Shift_R;
1247 case KSYM_Control_L:
1248 new_modifier = KMOD_Control_L;
1250 case KSYM_Control_R:
1251 new_modifier = KMOD_Control_R;
1254 new_modifier = KMOD_Meta_L;
1257 new_modifier = KMOD_Meta_R;
1260 new_modifier = KMOD_Alt_L;
1263 new_modifier = KMOD_Alt_R;
1269 if (key_status == KEY_PRESSED)
1270 current_modifiers |= new_modifier;
1272 current_modifiers &= ~new_modifier;
1275 return current_modifiers;
1278 KeyMod GetKeyModState()
1280 #if defined(TARGET_SDL)
1281 return (KeyMod)SDL_GetModState();
1283 return HandleKeyModState(KSYM_UNDEFINED, 0);
1287 KeyMod GetKeyModStateFromEvents()
1289 /* always use key modifier state as tracked from key events (this is needed
1290 if the modifier key event was injected into the event queue, but the key
1291 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1292 query the keys as held pressed on the keyboard) -- this case is currently
1293 only used to filter out clipboard insert events from "True X-Mouse" tool */
1295 return HandleKeyModState(KSYM_UNDEFINED, 0);
1298 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1300 if (event->type != EVENT_CLIENTMESSAGE)
1303 #if defined(TARGET_SDL)
1304 return TRUE; /* the only possible message here is SDL_QUIT */
1305 #elif defined(PLATFORM_UNIX)
1306 if ((event->window == window->drawable) &&
1307 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1315 /* ========================================================================= */
1316 /* joystick functions */
1317 /* ========================================================================= */
1319 void InitJoysticks()
1323 #if defined(NO_JOYSTICK)
1324 return; /* joysticks generally deactivated by compile-time directive */
1327 /* always start with reliable default values */
1328 joystick.status = JOYSTICK_NOT_AVAILABLE;
1329 for (i = 0; i < MAX_PLAYERS; i++)
1330 joystick.fd[i] = -1; /* joystick device closed */
1332 #if defined(TARGET_SDL)
1334 #elif defined(PLATFORM_UNIX)
1335 UnixInitJoysticks();
1336 #elif defined(PLATFORM_MSDOS)
1337 MSDOSInitJoysticks();
1341 for (i = 0; i < MAX_PLAYERS; i++)
1342 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1346 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1348 #if defined(TARGET_SDL)
1349 return SDLReadJoystick(nr, x, y, b1, b2);
1350 #elif defined(PLATFORM_UNIX)
1351 return UnixReadJoystick(nr, x, y, b1, b2);
1352 #elif defined(PLATFORM_MSDOS)
1353 return MSDOSReadJoystick(nr, x, y, b1, b2);