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 FadeScreen(Bitmap *bitmap_cross, int fade_mode, int fade_delay,
463 #if defined(TARGET_SDL)
464 SDLFadeScreen(bitmap_cross, fade_mode, fade_delay, post_delay);
466 X11FadeScreen(bitmap_cross, fade_mode, fade_delay, post_delay);
470 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
473 if (DrawingDeactivated(x, y, width, height))
476 sysFillRectangle(bitmap, x, y, width, height, color);
479 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
481 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
484 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
485 int width, int height)
487 if (DrawingOnBackground(x, y))
488 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
490 ClearRectangle(bitmap, x, y, width, height);
493 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
495 #if defined(TARGET_X11)
498 bitmap->clip_gc = clip_gc;
499 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
504 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
506 #if defined(TARGET_X11)
509 bitmap->clip_gc = clip_gc;
510 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
515 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
516 int src_x, int src_y, int width, int height,
517 int dst_x, int dst_y)
519 if (DrawingDeactivated(dst_x, dst_y, width, height))
522 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
523 dst_x, dst_y, BLIT_MASKED);
526 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
527 int src_x, int src_y, int width, int height,
528 int dst_x, int dst_y)
530 if (DrawingOnBackground(dst_x, dst_y))
532 /* draw background */
533 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
536 /* draw foreground */
537 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
538 dst_x - src_x, dst_y - src_y);
539 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
543 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
547 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
550 #if defined(TARGET_SDL)
551 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
553 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
557 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
560 #if defined(TARGET_SDL)
561 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
563 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
567 #if !defined(TARGET_X11_NATIVE)
568 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
569 int to_x, int to_y, Pixel pixel, int line_width)
573 for (x = 0; x < line_width; x++)
575 for (y = 0; y < line_width; y++)
577 int dx = x - line_width / 2;
578 int dy = y - line_width / 2;
580 if ((x == 0 && y == 0) ||
581 (x == 0 && y == line_width - 1) ||
582 (x == line_width - 1 && y == 0) ||
583 (x == line_width - 1 && y == line_width - 1))
586 #if defined(TARGET_SDL)
588 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
589 #elif defined(TARGET_ALLEGRO)
590 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
591 to_x + dx, to_y + dy, pixel);
598 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
600 #if !defined(TARGET_X11_NATIVE)
604 for (i = 0; i < num_points - 1; i++)
605 DrawLine(bitmap, points[i].x, points[i].y,
606 points[i + 1].x, points[i + 1].y, pixel, line_width);
609 SDLDrawLines(bitmap->surface, points, num_points, pixel);
612 XSetForeground(display, bitmap->line_gc[1], pixel);
613 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
614 (XPoint *)points, num_points, CoordModeOrigin);
618 Pixel GetPixel(Bitmap *bitmap, int x, int y)
620 if (x < 0 || x >= bitmap->width ||
621 y < 0 || y >= bitmap->height)
624 #if defined(TARGET_SDL)
625 return SDLGetPixel(bitmap, x, y);
626 #elif defined(TARGET_ALLEGRO)
627 return AllegroGetPixel(bitmap->drawable, x, y);
629 return X11GetPixel(bitmap, x, y);
633 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
634 unsigned int color_g, unsigned int color_b)
636 #if defined(TARGET_SDL)
637 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
638 #elif defined(TARGET_ALLEGRO)
639 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
641 return X11GetPixelFromRGB(color_r, color_g, color_b);
645 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
647 unsigned int color_r = (color >> 16) & 0xff;
648 unsigned int color_g = (color >> 8) & 0xff;
649 unsigned int color_b = (color >> 0) & 0xff;
651 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
654 /* execute all pending screen drawing operations */
655 void FlushDisplay(void)
662 /* execute and wait for all pending screen drawing operations */
663 void SyncDisplay(void)
666 XSync(display, FALSE);
670 void KeyboardAutoRepeatOn(void)
672 #if defined(TARGET_SDL)
673 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
674 SDL_DEFAULT_REPEAT_INTERVAL / 2);
675 SDL_EnableUNICODE(1);
678 XAutoRepeatOn(display);
682 void KeyboardAutoRepeatOff(void)
684 #if defined(TARGET_SDL)
685 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
686 SDL_EnableUNICODE(0);
689 XAutoRepeatOff(display);
693 boolean PointerInWindow(DrawWindow *window)
695 #if defined(TARGET_SDL)
703 /* if XQueryPointer() returns False, the pointer
704 is not on the same screen as the specified window */
705 return XQueryPointer(display, window->drawable, &root, &child,
706 &root_x, &root_y, &win_x, &win_y, &mask);
710 boolean SetVideoMode(boolean fullscreen)
712 #if defined(TARGET_SDL)
713 return SDLSetVideoMode(&backbuffer, fullscreen);
715 boolean success = TRUE;
717 if (fullscreen && video.fullscreen_available)
719 Error(ERR_WARN, "fullscreen not available in X11 version");
721 /* display error message only once */
722 video.fullscreen_available = FALSE;
731 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
733 #if defined(TARGET_SDL)
734 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
735 (!fullscreen && video.fullscreen_enabled))
736 fullscreen = SetVideoMode(fullscreen);
742 Bitmap *LoadImage(char *filename)
746 #if defined(TARGET_SDL)
747 new_bitmap = SDLLoadImage(filename);
749 new_bitmap = X11LoadImage(filename);
753 new_bitmap->source_filename = getStringCopy(filename);
758 Bitmap *LoadCustomImage(char *basename)
760 char *filename = getCustomImageFilename(basename);
763 if (filename == NULL)
764 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
766 if ((new_bitmap = LoadImage(filename)) == NULL)
767 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
772 void ReloadCustomImage(Bitmap *bitmap, char *basename)
774 char *filename = getCustomImageFilename(basename);
777 if (filename == NULL) /* (should never happen) */
779 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
783 if (strEqual(filename, bitmap->source_filename))
785 /* The old and new image are the same (have the same filename and path).
786 This usually means that this image does not exist in this graphic set
787 and a fallback to the existing image is done. */
792 if ((new_bitmap = LoadImage(filename)) == NULL)
794 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
798 if (bitmap->width != new_bitmap->width ||
799 bitmap->height != new_bitmap->height)
801 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
803 FreeBitmap(new_bitmap);
807 TransferBitmapPointers(new_bitmap, bitmap);
811 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
813 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
815 #if defined(TARGET_SDL)
816 SDLZoomBitmap(src_bitmap, dst_bitmap);
818 X11ZoomBitmap(src_bitmap, dst_bitmap);
824 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
825 boolean create_small_bitmaps)
828 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
829 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
830 int new_width, new_height;
832 /* calculate new image dimensions for normal sized image */
833 width_1 = old_bitmap->width * zoom_factor;
834 height_1 = old_bitmap->height * zoom_factor;
836 /* get image with normal size (this might require scaling up) */
837 if (zoom_factor != 1)
838 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
840 tmp_bitmap_1 = old_bitmap;
842 /* this is only needed to make compilers happy */
843 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
845 if (create_small_bitmaps)
847 /* calculate new image dimensions for small images */
848 width_2 = width_1 / 2;
849 height_2 = height_1 / 2;
850 width_4 = width_1 / 4;
851 height_4 = height_1 / 4;
852 width_8 = width_1 / 8;
853 height_8 = height_1 / 8;
855 /* get image with 1/2 of normal size (for use in the level editor) */
856 if (zoom_factor != 2)
857 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
859 tmp_bitmap_2 = old_bitmap;
861 /* get image with 1/4 of normal size (for use in the level editor) */
862 if (zoom_factor != 4)
863 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
865 tmp_bitmap_4 = old_bitmap;
867 /* get image with 1/8 of normal size (for use on the preview screen) */
868 if (zoom_factor != 8)
869 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
871 tmp_bitmap_8 = old_bitmap;
874 /* if image was scaled up, create new clipmask for normal size image */
875 if (zoom_factor != 1)
877 #if defined(TARGET_X11)
878 if (old_bitmap->clip_mask)
879 XFreePixmap(display, old_bitmap->clip_mask);
881 old_bitmap->clip_mask =
882 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
884 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
886 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
888 if (old_bitmap->surface_masked)
889 SDL_FreeSurface(old_bitmap->surface_masked);
891 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
892 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
893 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
894 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
895 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
899 if (create_small_bitmaps)
902 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
904 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
906 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
907 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
909 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
910 width_1 / 2, height_1);
911 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
912 3 * width_1 / 4, height_1);
917 new_height = height_1;
919 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
922 if (create_small_bitmaps)
924 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
925 if (zoom_factor != 1)
926 FreeBitmap(tmp_bitmap_1);
928 if (zoom_factor != 2)
929 FreeBitmap(tmp_bitmap_2);
931 if (zoom_factor != 4)
932 FreeBitmap(tmp_bitmap_4);
934 if (zoom_factor != 8)
935 FreeBitmap(tmp_bitmap_8);
938 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
939 #if defined(TARGET_SDL)
940 swap_bitmap.surface = old_bitmap->surface;
941 old_bitmap->surface = new_bitmap->surface;
942 new_bitmap->surface = swap_bitmap.surface;
944 swap_bitmap.drawable = old_bitmap->drawable;
945 old_bitmap->drawable = new_bitmap->drawable;
946 new_bitmap->drawable = swap_bitmap.drawable;
949 old_bitmap->width = new_bitmap->width;
950 old_bitmap->height = new_bitmap->height;
952 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
955 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
957 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
960 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
962 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
966 /* ------------------------------------------------------------------------- */
967 /* mouse pointer functions */
968 /* ------------------------------------------------------------------------- */
970 #if !defined(PLATFORM_MSDOS)
972 static const char *cursor_image_playfield[] =
974 /* width height num_colors chars_per_pixel */
983 /* some people complained about a "white dot" on the screen and thought it
984 was a graphical error... OK, let's just remove the whole pointer :-) */
1032 #if defined(TARGET_SDL)
1033 static const int cursor_bit_order = BIT_ORDER_MSB;
1034 #elif defined(TARGET_X11_NATIVE)
1035 static const int cursor_bit_order = BIT_ORDER_LSB;
1038 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1040 struct MouseCursorInfo *cursor;
1041 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1042 int header_lines = 4;
1045 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1047 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1050 for (y = 0; y < cursor->width; y++)
1052 for (x = 0; x < cursor->height; x++)
1055 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1060 cursor->data[i] = cursor->mask[i] = 0;
1063 switch (image[header_lines + y][x])
1066 cursor->data[i] |= bit_mask;
1067 cursor->mask[i] |= bit_mask;
1071 cursor->mask[i] |= bit_mask;
1080 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1084 #endif /* !PLATFORM_MSDOS */
1086 void SetMouseCursor(int mode)
1088 #if !defined(PLATFORM_MSDOS)
1089 static struct MouseCursorInfo *cursor_playfield = NULL;
1091 if (cursor_playfield == NULL)
1092 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1094 #if defined(TARGET_SDL)
1095 SDLSetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1096 #elif defined(TARGET_X11_NATIVE)
1097 X11SetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1103 /* ========================================================================= */
1104 /* audio functions */
1105 /* ========================================================================= */
1107 void OpenAudio(void)
1109 /* always start with reliable default values */
1110 audio.sound_available = FALSE;
1111 audio.music_available = FALSE;
1112 audio.loops_available = FALSE;
1114 audio.sound_enabled = FALSE;
1115 audio.sound_deactivated = FALSE;
1117 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1118 audio.mixer_pid = 0;
1119 audio.device_name = NULL;
1120 audio.device_fd = -1;
1122 audio.num_channels = 0;
1123 audio.music_channel = 0;
1124 audio.first_sound_channel = 0;
1126 #if defined(TARGET_SDL)
1128 #elif defined(PLATFORM_UNIX)
1130 #elif defined(PLATFORM_MSDOS)
1135 void CloseAudio(void)
1137 #if defined(TARGET_SDL)
1139 #elif defined(PLATFORM_UNIX)
1141 #elif defined(PLATFORM_MSDOS)
1145 audio.sound_enabled = FALSE;
1148 void SetAudioMode(boolean enabled)
1150 if (!audio.sound_available)
1153 audio.sound_enabled = enabled;
1157 /* ========================================================================= */
1158 /* event functions */
1159 /* ========================================================================= */
1161 void InitEventFilter(EventFilter filter_function)
1163 #if defined(TARGET_SDL)
1164 /* set event filter to filter out certain events */
1165 SDL_SetEventFilter(filter_function);
1169 boolean PendingEvent(void)
1171 #if defined(TARGET_SDL)
1172 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1174 return (XPending(display) ? TRUE : FALSE);
1178 void NextEvent(Event *event)
1180 #if defined(TARGET_SDL)
1181 SDLNextEvent(event);
1183 XNextEvent(display, event);
1187 void PeekEvent(Event *event)
1189 #if defined(TARGET_SDL)
1190 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1192 XPeekEvent(display, event);
1196 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1198 #if defined(TARGET_SDL)
1201 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1202 (int)event->keysym.unicode,
1203 (int)event->keysym.sym,
1204 (int)SDL_GetModState());
1207 if (with_modifiers &&
1208 event->keysym.unicode > 0x0000 &&
1209 event->keysym.unicode < 0x2000)
1210 return event->keysym.unicode;
1212 return event->keysym.sym;
1217 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1218 (int)XLookupKeysym(event, event->state),
1219 (int)XLookupKeysym(event, 0));
1223 return XLookupKeysym(event, event->state);
1225 return XLookupKeysym(event, 0);
1229 KeyMod HandleKeyModState(Key key, int key_status)
1231 static KeyMod current_modifiers = KMOD_None;
1233 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1235 KeyMod new_modifier = KMOD_None;
1240 new_modifier = KMOD_Shift_L;
1243 new_modifier = KMOD_Shift_R;
1245 case KSYM_Control_L:
1246 new_modifier = KMOD_Control_L;
1248 case KSYM_Control_R:
1249 new_modifier = KMOD_Control_R;
1252 new_modifier = KMOD_Meta_L;
1255 new_modifier = KMOD_Meta_R;
1258 new_modifier = KMOD_Alt_L;
1261 new_modifier = KMOD_Alt_R;
1267 if (key_status == KEY_PRESSED)
1268 current_modifiers |= new_modifier;
1270 current_modifiers &= ~new_modifier;
1273 return current_modifiers;
1276 KeyMod GetKeyModState()
1278 #if defined(TARGET_SDL)
1279 return (KeyMod)SDL_GetModState();
1281 return HandleKeyModState(KSYM_UNDEFINED, 0);
1285 KeyMod GetKeyModStateFromEvents()
1287 /* always use key modifier state as tracked from key events (this is needed
1288 if the modifier key event was injected into the event queue, but the key
1289 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1290 query the keys as held pressed on the keyboard) -- this case is currently
1291 only used to filter out clipboard insert events from "True X-Mouse" tool */
1293 return HandleKeyModState(KSYM_UNDEFINED, 0);
1296 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1298 if (event->type != EVENT_CLIENTMESSAGE)
1301 #if defined(TARGET_SDL)
1302 return TRUE; /* the only possible message here is SDL_QUIT */
1303 #elif defined(PLATFORM_UNIX)
1304 if ((event->window == window->drawable) &&
1305 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1313 /* ========================================================================= */
1314 /* joystick functions */
1315 /* ========================================================================= */
1317 void InitJoysticks()
1321 #if defined(NO_JOYSTICK)
1322 return; /* joysticks generally deactivated by compile-time directive */
1325 /* always start with reliable default values */
1326 joystick.status = JOYSTICK_NOT_AVAILABLE;
1327 for (i = 0; i < MAX_PLAYERS; i++)
1328 joystick.fd[i] = -1; /* joystick device closed */
1330 #if defined(TARGET_SDL)
1332 #elif defined(PLATFORM_UNIX)
1333 UnixInitJoysticks();
1334 #elif defined(PLATFORM_MSDOS)
1335 MSDOSInitJoysticks();
1339 for (i = 0; i < MAX_PLAYERS; i++)
1340 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1344 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1346 #if defined(TARGET_SDL)
1347 return SDLReadJoystick(nr, x, y, b1, b2);
1348 #elif defined(PLATFORM_UNIX)
1349 return UnixReadJoystick(nr, x, y, b1, b2);
1350 #elif defined(PLATFORM_MSDOS)
1351 return MSDOSReadJoystick(nr, x, y, b1, b2);