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 InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
201 gfx.draw_busy_anim_function = draw_busy_anim_function;
204 void SetDrawDeactivationMask(int draw_deactivation_mask)
206 gfx.draw_deactivation_mask = draw_deactivation_mask;
209 void SetDrawBackgroundMask(int draw_background_mask)
211 gfx.draw_background_mask = draw_background_mask;
214 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
215 int dest_x, int dest_y, int width, int height)
217 int bitmap_xsize = width;
218 int bitmap_ysize = height;
219 int tile_xsize = tile->width;
220 int tile_ysize = tile->height;
221 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
222 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
225 for (y = 0; y < tile_ysteps; y++)
227 for (x = 0; x < tile_xsteps; x++)
229 int draw_x = dest_x + x * tile_xsize;
230 int draw_y = dest_y + y * tile_ysize;
231 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
232 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
234 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
239 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
241 if (background_bitmap_tile != NULL)
242 gfx.background_bitmap_mask |= mask;
244 gfx.background_bitmap_mask &= ~mask;
246 if (gfx.background_bitmap == NULL)
247 gfx.background_bitmap = CreateBitmap(video.width, video.height,
250 if (background_bitmap_tile == NULL) /* empty background requested */
253 if (mask == REDRAW_ALL)
254 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
255 0, 0, video.width, video.height);
256 else if (mask == REDRAW_FIELD)
257 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
258 gfx.real_sx, gfx.real_sy,
259 gfx.full_sxsize, gfx.full_sysize);
260 else if (mask == REDRAW_DOOR_1)
262 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
264 gfx.dxsize, gfx.dysize);
268 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
270 /* remove every mask before setting mask for window */
271 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
272 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
273 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
276 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
278 /* remove window area mask before setting mask for main area */
279 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
280 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
281 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
284 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
286 /* remove window area mask before setting mask for door area */
287 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
288 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
289 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
293 /* ========================================================================= */
294 /* video functions */
295 /* ========================================================================= */
297 inline static int GetRealDepth(int depth)
299 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
302 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
303 int width, int height, Pixel color)
305 #if defined(TARGET_SDL)
306 SDLFillRectangle(bitmap, x, y, width, height, color);
308 X11FillRectangle(bitmap, x, y, width, height, color);
312 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
313 int src_x, int src_y, int width, int height,
314 int dst_x, int dst_y, int mask_mode)
316 #if defined(TARGET_SDL)
317 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
318 dst_x, dst_y, mask_mode);
320 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
321 dst_x, dst_y, mask_mode);
325 void InitVideoDisplay(void)
327 #if defined(TARGET_SDL)
328 SDLInitVideoDisplay();
330 X11InitVideoDisplay();
334 void CloseVideoDisplay(void)
336 KeyboardAutoRepeatOn();
338 #if defined(TARGET_SDL)
339 SDL_QuitSubSystem(SDL_INIT_VIDEO);
342 XCloseDisplay(display);
346 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
349 video.height = height;
350 video.depth = GetRealDepth(depth);
352 video.fullscreen_available = FULLSCREEN_STATUS;
353 video.fullscreen_enabled = FALSE;
354 video.fullscreen_modes = NULL;
355 video.fullscreen_mode_current = NULL;
357 #if defined(TARGET_SDL)
358 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
360 X11InitVideoBuffer(&backbuffer, &window);
366 Bitmap *CreateBitmapStruct(void)
368 #if defined(TARGET_SDL)
369 return checked_calloc(sizeof(struct SDLSurfaceInfo));
371 return checked_calloc(sizeof(struct X11DrawableInfo));
375 Bitmap *CreateBitmap(int width, int height, int depth)
377 Bitmap *new_bitmap = CreateBitmapStruct();
378 int real_depth = GetRealDepth(depth);
380 #if defined(TARGET_SDL)
381 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
383 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
386 new_bitmap->width = width;
387 new_bitmap->height = height;
392 inline static void FreeBitmapPointers(Bitmap *bitmap)
397 #if defined(TARGET_SDL)
398 SDLFreeBitmapPointers(bitmap);
400 X11FreeBitmapPointers(bitmap);
403 checked_free(bitmap->source_filename);
404 bitmap->source_filename = NULL;
407 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
410 if (src_bitmap == NULL || dst_bitmap == NULL)
413 FreeBitmapPointers(dst_bitmap);
415 *dst_bitmap = *src_bitmap;
418 void FreeBitmap(Bitmap *bitmap)
423 FreeBitmapPointers(bitmap);
428 void CloseWindow(DrawWindow *window)
430 #if defined(TARGET_X11)
431 if (window->drawable)
433 XUnmapWindow(display, window->drawable);
434 XDestroyWindow(display, window->drawable);
437 XFreeGC(display, window->gc);
441 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
444 if (draw_mask == REDRAW_NONE)
447 if (draw_mask & REDRAW_ALL)
450 if ((draw_mask & REDRAW_FIELD) &&
451 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
454 if ((draw_mask & REDRAW_DOOR_1) &&
455 x >= gfx.dx && y < gfx.dy + gfx.dysize)
458 if ((draw_mask & REDRAW_DOOR_2) &&
459 x >= gfx.dx && y >= gfx.vy)
465 boolean DrawingDeactivated(int x, int y, int width, int height)
467 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
470 boolean DrawingOnBackground(int x, int y)
472 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
473 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
476 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
477 int src_x, int src_y, int width, int height,
478 int dst_x, int dst_y)
480 if (DrawingDeactivated(dst_x, dst_y, width, height))
483 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
484 dst_x, dst_y, BLIT_OPAQUE);
487 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
488 int fade_mode, int fade_delay, int post_delay,
489 void (*draw_border_function)(void))
491 #if defined(TARGET_SDL)
492 SDLFadeRectangle(bitmap_cross, x, y, width, height,
493 fade_mode, fade_delay, post_delay, draw_border_function);
495 X11FadeRectangle(bitmap_cross, x, y, width, height,
496 fade_mode, fade_delay, post_delay, draw_border_function);
500 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
503 if (DrawingDeactivated(x, y, width, height))
506 sysFillRectangle(bitmap, x, y, width, height, color);
509 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
511 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
514 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
515 int width, int height)
517 if (DrawingOnBackground(x, y))
518 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
520 ClearRectangle(bitmap, x, y, width, height);
523 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
525 #if defined(TARGET_X11)
528 bitmap->clip_gc = clip_gc;
529 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
534 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
536 #if defined(TARGET_X11)
539 bitmap->clip_gc = clip_gc;
540 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
545 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
546 int src_x, int src_y, int width, int height,
547 int dst_x, int dst_y)
549 if (DrawingDeactivated(dst_x, dst_y, width, height))
552 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
553 dst_x, dst_y, BLIT_MASKED);
556 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
557 int src_x, int src_y, int width, int height,
558 int dst_x, int dst_y)
560 if (DrawingOnBackground(dst_x, dst_y))
562 /* draw background */
563 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
566 /* draw foreground */
567 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
568 dst_x - src_x, dst_y - src_y);
569 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
573 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
577 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
580 #if defined(TARGET_SDL)
581 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
583 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
587 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
590 #if defined(TARGET_SDL)
591 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
593 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
597 #if !defined(TARGET_X11_NATIVE)
598 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
599 int to_x, int to_y, Pixel pixel, int line_width)
603 for (x = 0; x < line_width; x++)
605 for (y = 0; y < line_width; y++)
607 int dx = x - line_width / 2;
608 int dy = y - line_width / 2;
610 if ((x == 0 && y == 0) ||
611 (x == 0 && y == line_width - 1) ||
612 (x == line_width - 1 && y == 0) ||
613 (x == line_width - 1 && y == line_width - 1))
616 #if defined(TARGET_SDL)
618 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
619 #elif defined(TARGET_ALLEGRO)
620 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
621 to_x + dx, to_y + dy, pixel);
628 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
630 #if !defined(TARGET_X11_NATIVE)
634 for (i = 0; i < num_points - 1; i++)
635 DrawLine(bitmap, points[i].x, points[i].y,
636 points[i + 1].x, points[i + 1].y, pixel, line_width);
639 SDLDrawLines(bitmap->surface, points, num_points, pixel);
642 XSetForeground(display, bitmap->line_gc[1], pixel);
643 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
644 (XPoint *)points, num_points, CoordModeOrigin);
648 Pixel GetPixel(Bitmap *bitmap, int x, int y)
650 if (x < 0 || x >= bitmap->width ||
651 y < 0 || y >= bitmap->height)
654 #if defined(TARGET_SDL)
655 return SDLGetPixel(bitmap, x, y);
656 #elif defined(TARGET_ALLEGRO)
657 return AllegroGetPixel(bitmap->drawable, x, y);
659 return X11GetPixel(bitmap, x, y);
663 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
664 unsigned int color_g, unsigned int color_b)
666 #if defined(TARGET_SDL)
667 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
668 #elif defined(TARGET_ALLEGRO)
669 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
671 return X11GetPixelFromRGB(color_r, color_g, color_b);
675 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
677 unsigned int color_r = (color >> 16) & 0xff;
678 unsigned int color_g = (color >> 8) & 0xff;
679 unsigned int color_b = (color >> 0) & 0xff;
681 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
684 /* execute all pending screen drawing operations */
685 void FlushDisplay(void)
692 /* execute and wait for all pending screen drawing operations */
693 void SyncDisplay(void)
696 XSync(display, FALSE);
700 void KeyboardAutoRepeatOn(void)
702 #if defined(TARGET_SDL)
703 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
704 SDL_DEFAULT_REPEAT_INTERVAL / 2);
705 SDL_EnableUNICODE(1);
708 XAutoRepeatOn(display);
712 void KeyboardAutoRepeatOff(void)
714 #if defined(TARGET_SDL)
715 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
716 SDL_EnableUNICODE(0);
719 XAutoRepeatOff(display);
723 boolean PointerInWindow(DrawWindow *window)
725 #if defined(TARGET_SDL)
733 /* if XQueryPointer() returns False, the pointer
734 is not on the same screen as the specified window */
735 return XQueryPointer(display, window->drawable, &root, &child,
736 &root_x, &root_y, &win_x, &win_y, &mask);
740 boolean SetVideoMode(boolean fullscreen)
742 #if defined(TARGET_SDL)
743 return SDLSetVideoMode(&backbuffer, fullscreen);
745 boolean success = TRUE;
747 if (fullscreen && video.fullscreen_available)
749 Error(ERR_WARN, "fullscreen not available in X11 version");
751 /* display error message only once */
752 video.fullscreen_available = FALSE;
761 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
763 #if defined(TARGET_SDL)
764 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
765 (!fullscreen && video.fullscreen_enabled))
766 fullscreen = SetVideoMode(fullscreen);
772 Bitmap *LoadImage(char *filename)
776 #if defined(TARGET_SDL)
777 new_bitmap = SDLLoadImage(filename);
779 new_bitmap = X11LoadImage(filename);
783 new_bitmap->source_filename = getStringCopy(filename);
788 Bitmap *LoadCustomImage(char *basename)
790 char *filename = getCustomImageFilename(basename);
793 if (filename == NULL)
794 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
796 if ((new_bitmap = LoadImage(filename)) == NULL)
797 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
802 void ReloadCustomImage(Bitmap *bitmap, char *basename)
804 char *filename = getCustomImageFilename(basename);
807 if (filename == NULL) /* (should never happen) */
809 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
813 if (strEqual(filename, bitmap->source_filename))
815 /* The old and new image are the same (have the same filename and path).
816 This usually means that this image does not exist in this graphic set
817 and a fallback to the existing image is done. */
822 if ((new_bitmap = LoadImage(filename)) == NULL)
824 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
828 if (bitmap->width != new_bitmap->width ||
829 bitmap->height != new_bitmap->height)
831 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
833 FreeBitmap(new_bitmap);
837 TransferBitmapPointers(new_bitmap, bitmap);
841 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
843 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
845 #if defined(TARGET_SDL)
846 SDLZoomBitmap(src_bitmap, dst_bitmap);
848 X11ZoomBitmap(src_bitmap, dst_bitmap);
854 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
855 boolean create_small_bitmaps)
859 Bitmap *tmp_bitmap_1;
860 Bitmap *tmp_bitmap_2;
861 Bitmap *tmp_bitmap_4;
862 Bitmap *tmp_bitmap_8;
863 Bitmap *tmp_bitmap_16;
864 Bitmap *tmp_bitmap_32;
865 int width_1, height_1;
866 int width_2, height_2;
867 int width_4, height_4;
868 int width_8, height_8;
869 int width_16, height_16;
870 int width_32, height_32;
871 int new_width, new_height;
873 /* calculate new image dimensions for normal sized image */
874 width_1 = old_bitmap->width * zoom_factor;
875 height_1 = old_bitmap->height * zoom_factor;
877 /* get image with normal size (this might require scaling up) */
878 if (zoom_factor != 1)
879 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
881 tmp_bitmap_1 = old_bitmap;
883 /* this is only needed to make compilers happy */
887 tmp_bitmap_16 = NULL;
888 tmp_bitmap_32 = NULL;
890 if (create_small_bitmaps)
892 /* calculate new image dimensions for small images */
893 width_2 = width_1 / 2;
894 height_2 = height_1 / 2;
895 width_4 = width_1 / 4;
896 height_4 = height_1 / 4;
897 width_8 = width_1 / 8;
898 height_8 = height_1 / 8;
899 width_16 = width_1 / 16;
900 height_16 = height_1 / 16;
901 width_32 = width_1 / 32;
902 height_32 = height_1 / 32;
906 /* get image with 1/2 of normal size (for use in the level editor) */
907 if (zoom_factor != 2)
908 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
910 tmp_bitmap_2 = old_bitmap;
914 /* get image with 1/4 of normal size (for use in the level editor) */
915 if (zoom_factor != 4)
916 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
918 tmp_bitmap_4 = old_bitmap;
922 /* get image with 1/8 of normal size (for use on the preview screen) */
923 if (zoom_factor != 8)
924 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
926 tmp_bitmap_8 = old_bitmap;
930 /* get image with 1/16 of normal size (for use on the preview screen) */
931 if (zoom_factor != 16)
932 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
934 tmp_bitmap_16 = old_bitmap;
938 /* get image with 1/32 of normal size (for use on the preview screen) */
939 if (zoom_factor != 32)
940 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
942 tmp_bitmap_32 = old_bitmap;
948 /* if image was scaled up, create new clipmask for normal size image */
949 if (zoom_factor != 1)
951 #if defined(TARGET_X11)
952 if (old_bitmap->clip_mask)
953 XFreePixmap(display, old_bitmap->clip_mask);
955 old_bitmap->clip_mask =
956 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
958 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
960 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
962 if (old_bitmap->surface_masked)
963 SDL_FreeSurface(old_bitmap->surface_masked);
965 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
966 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
967 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
968 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
969 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
974 if (create_small_bitmaps)
977 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
979 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
981 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
982 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
984 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
985 width_1 / 2, height_1);
986 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
987 3 * width_1 / 4, height_1);
988 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
989 7 * width_1 / 8, height_1);
990 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
991 15 * width_1 / 16, height_1);
998 new_height = height_1;
1000 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1003 if (create_small_bitmaps)
1005 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1006 if (zoom_factor != 1)
1007 FreeBitmap(tmp_bitmap_1);
1009 if (zoom_factor != 2)
1010 FreeBitmap(tmp_bitmap_2);
1012 if (zoom_factor != 4)
1013 FreeBitmap(tmp_bitmap_4);
1015 if (zoom_factor != 8)
1016 FreeBitmap(tmp_bitmap_8);
1018 if (zoom_factor != 16)
1019 FreeBitmap(tmp_bitmap_16);
1021 if (zoom_factor != 32)
1022 FreeBitmap(tmp_bitmap_32);
1025 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1026 #if defined(TARGET_SDL)
1027 swap_bitmap.surface = old_bitmap->surface;
1028 old_bitmap->surface = new_bitmap->surface;
1029 new_bitmap->surface = swap_bitmap.surface;
1031 swap_bitmap.drawable = old_bitmap->drawable;
1032 old_bitmap->drawable = new_bitmap->drawable;
1033 new_bitmap->drawable = swap_bitmap.drawable;
1036 old_bitmap->width = new_bitmap->width;
1037 old_bitmap->height = new_bitmap->height;
1040 /* this replaces all blit masks created when loading -- maybe optimize this */
1042 #if defined(TARGET_X11)
1043 if (old_bitmap->clip_mask)
1044 XFreePixmap(display, old_bitmap->clip_mask);
1046 old_bitmap->clip_mask =
1047 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1049 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1051 SDL_Surface *old_surface = old_bitmap->surface;
1053 if (old_bitmap->surface_masked)
1054 SDL_FreeSurface(old_bitmap->surface_masked);
1056 SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
1057 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1058 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1059 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1060 SDL_SetColorKey(old_surface, 0, 0); /* reset transparent pixel */
1065 UPDATE_BUSY_STATE();
1067 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1070 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1072 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1075 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1077 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1081 /* ------------------------------------------------------------------------- */
1082 /* mouse pointer functions */
1083 /* ------------------------------------------------------------------------- */
1085 #if !defined(PLATFORM_MSDOS)
1086 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1087 /* XPM image definitions */
1088 static const char *cursor_image_none[] =
1090 /* width height num_colors chars_per_pixel */
1119 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1120 static const char *cursor_image_dot[] =
1122 /* width height num_colors chars_per_pixel */
1151 static const char **cursor_image_playfield = cursor_image_dot;
1153 /* some people complained about a "white dot" on the screen and thought it
1154 was a graphical error... OK, let's just remove the whole pointer :-) */
1155 static const char **cursor_image_playfield = cursor_image_none;
1158 #if defined(TARGET_SDL)
1159 static const int cursor_bit_order = BIT_ORDER_MSB;
1160 #elif defined(TARGET_X11_NATIVE)
1161 static const int cursor_bit_order = BIT_ORDER_LSB;
1164 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1166 struct MouseCursorInfo *cursor;
1167 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1168 int header_lines = 4;
1171 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1173 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1176 for (y = 0; y < cursor->width; y++)
1178 for (x = 0; x < cursor->height; x++)
1181 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1186 cursor->data[i] = cursor->mask[i] = 0;
1189 switch (image[header_lines + y][x])
1192 cursor->data[i] |= bit_mask;
1193 cursor->mask[i] |= bit_mask;
1197 cursor->mask[i] |= bit_mask;
1206 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1210 #endif /* !PLATFORM_MSDOS */
1212 void SetMouseCursor(int mode)
1214 #if !defined(PLATFORM_MSDOS)
1215 static struct MouseCursorInfo *cursor_none = NULL;
1216 static struct MouseCursorInfo *cursor_playfield = NULL;
1217 struct MouseCursorInfo *cursor_new;
1219 if (cursor_none == NULL)
1220 cursor_none = get_cursor_from_image(cursor_image_none);
1222 if (cursor_playfield == NULL)
1223 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1225 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1226 mode == CURSOR_NONE ? cursor_none :
1227 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1229 #if defined(TARGET_SDL)
1230 SDLSetMouseCursor(cursor_new);
1231 #elif defined(TARGET_X11_NATIVE)
1232 X11SetMouseCursor(cursor_new);
1238 /* ========================================================================= */
1239 /* audio functions */
1240 /* ========================================================================= */
1242 void OpenAudio(void)
1244 /* always start with reliable default values */
1245 audio.sound_available = FALSE;
1246 audio.music_available = FALSE;
1247 audio.loops_available = FALSE;
1249 audio.sound_enabled = FALSE;
1250 audio.sound_deactivated = FALSE;
1252 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1253 audio.mixer_pid = 0;
1254 audio.device_name = NULL;
1255 audio.device_fd = -1;
1257 audio.num_channels = 0;
1258 audio.music_channel = 0;
1259 audio.first_sound_channel = 0;
1261 #if defined(TARGET_SDL)
1263 #elif defined(PLATFORM_UNIX)
1265 #elif defined(PLATFORM_MSDOS)
1270 void CloseAudio(void)
1272 #if defined(TARGET_SDL)
1274 #elif defined(PLATFORM_UNIX)
1276 #elif defined(PLATFORM_MSDOS)
1280 audio.sound_enabled = FALSE;
1283 void SetAudioMode(boolean enabled)
1285 if (!audio.sound_available)
1288 audio.sound_enabled = enabled;
1292 /* ========================================================================= */
1293 /* event functions */
1294 /* ========================================================================= */
1296 void InitEventFilter(EventFilter filter_function)
1298 #if defined(TARGET_SDL)
1299 /* set event filter to filter out certain events */
1300 SDL_SetEventFilter(filter_function);
1304 boolean PendingEvent(void)
1306 #if defined(TARGET_SDL)
1307 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1309 return (XPending(display) ? TRUE : FALSE);
1313 void NextEvent(Event *event)
1315 #if defined(TARGET_SDL)
1316 SDLNextEvent(event);
1318 XNextEvent(display, event);
1322 void PeekEvent(Event *event)
1324 #if defined(TARGET_SDL)
1325 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1327 XPeekEvent(display, event);
1331 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1333 #if defined(TARGET_SDL)
1336 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1337 (int)event->keysym.unicode,
1338 (int)event->keysym.sym,
1339 (int)SDL_GetModState());
1342 if (with_modifiers &&
1343 event->keysym.unicode > 0x0000 &&
1344 event->keysym.unicode < 0x2000)
1345 return event->keysym.unicode;
1347 return event->keysym.sym;
1352 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1353 (int)XLookupKeysym(event, event->state),
1354 (int)XLookupKeysym(event, 0));
1358 return XLookupKeysym(event, event->state);
1360 return XLookupKeysym(event, 0);
1364 KeyMod HandleKeyModState(Key key, int key_status)
1366 static KeyMod current_modifiers = KMOD_None;
1368 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1370 KeyMod new_modifier = KMOD_None;
1375 new_modifier = KMOD_Shift_L;
1378 new_modifier = KMOD_Shift_R;
1380 case KSYM_Control_L:
1381 new_modifier = KMOD_Control_L;
1383 case KSYM_Control_R:
1384 new_modifier = KMOD_Control_R;
1387 new_modifier = KMOD_Meta_L;
1390 new_modifier = KMOD_Meta_R;
1393 new_modifier = KMOD_Alt_L;
1396 new_modifier = KMOD_Alt_R;
1402 if (key_status == KEY_PRESSED)
1403 current_modifiers |= new_modifier;
1405 current_modifiers &= ~new_modifier;
1408 return current_modifiers;
1411 KeyMod GetKeyModState()
1413 #if defined(TARGET_SDL)
1414 return (KeyMod)SDL_GetModState();
1416 return HandleKeyModState(KSYM_UNDEFINED, 0);
1420 KeyMod GetKeyModStateFromEvents()
1422 /* always use key modifier state as tracked from key events (this is needed
1423 if the modifier key event was injected into the event queue, but the key
1424 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1425 query the keys as held pressed on the keyboard) -- this case is currently
1426 only used to filter out clipboard insert events from "True X-Mouse" tool */
1428 return HandleKeyModState(KSYM_UNDEFINED, 0);
1431 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1433 if (event->type != EVENT_CLIENTMESSAGE)
1436 #if defined(TARGET_SDL)
1437 return TRUE; /* the only possible message here is SDL_QUIT */
1438 #elif defined(PLATFORM_UNIX)
1439 if ((event->window == window->drawable) &&
1440 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1448 /* ========================================================================= */
1449 /* joystick functions */
1450 /* ========================================================================= */
1452 void InitJoysticks()
1456 #if defined(NO_JOYSTICK)
1457 return; /* joysticks generally deactivated by compile-time directive */
1460 /* always start with reliable default values */
1461 joystick.status = JOYSTICK_NOT_AVAILABLE;
1462 for (i = 0; i < MAX_PLAYERS; i++)
1463 joystick.fd[i] = -1; /* joystick device closed */
1465 #if defined(TARGET_SDL)
1467 #elif defined(PLATFORM_UNIX)
1468 UnixInitJoysticks();
1469 #elif defined(PLATFORM_MSDOS)
1470 MSDOSInitJoysticks();
1474 for (i = 0; i < MAX_PLAYERS; i++)
1475 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1479 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1481 #if defined(TARGET_SDL)
1482 return SDLReadJoystick(nr, x, y, b1, b2);
1483 #elif defined(PLATFORM_UNIX)
1484 return UnixReadJoystick(nr, x, y, b1, b2);
1485 #elif defined(PLATFORM_MSDOS)
1486 return MSDOSReadJoystick(nr, x, y, b1, b2);