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 InitGfxCustomArtworkInfo()
206 gfx.override_level_graphics = FALSE;
207 gfx.override_level_sounds = FALSE;
208 gfx.override_level_music = FALSE;
210 gfx.draw_init_text = TRUE;
213 void SetDrawDeactivationMask(int draw_deactivation_mask)
215 gfx.draw_deactivation_mask = draw_deactivation_mask;
218 void SetDrawBackgroundMask(int draw_background_mask)
220 gfx.draw_background_mask = draw_background_mask;
223 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
224 int dest_x, int dest_y, int width, int height)
226 int bitmap_xsize = width;
227 int bitmap_ysize = height;
228 int tile_xsize = tile->width;
229 int tile_ysize = tile->height;
230 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
231 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
234 for (y = 0; y < tile_ysteps; y++)
236 for (x = 0; x < tile_xsteps; x++)
238 int draw_x = dest_x + x * tile_xsize;
239 int draw_y = dest_y + y * tile_ysize;
240 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
241 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
243 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
248 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
250 if (background_bitmap_tile != NULL)
251 gfx.background_bitmap_mask |= mask;
253 gfx.background_bitmap_mask &= ~mask;
255 if (gfx.background_bitmap == NULL)
256 gfx.background_bitmap = CreateBitmap(video.width, video.height,
259 if (background_bitmap_tile == NULL) /* empty background requested */
262 if (mask == REDRAW_ALL)
263 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
264 0, 0, video.width, video.height);
265 else if (mask == REDRAW_FIELD)
266 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
267 gfx.real_sx, gfx.real_sy,
268 gfx.full_sxsize, gfx.full_sysize);
269 else if (mask == REDRAW_DOOR_1)
271 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
273 gfx.dxsize, gfx.dysize);
277 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
279 /* remove every mask before setting mask for window */
280 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
281 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
282 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
285 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
287 /* remove window area mask before setting mask for main area */
288 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
289 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
290 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
293 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
295 /* remove window area mask before setting mask for door area */
296 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
297 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
298 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
302 /* ========================================================================= */
303 /* video functions */
304 /* ========================================================================= */
306 inline static int GetRealDepth(int depth)
308 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
311 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
312 int width, int height, Pixel color)
314 #if defined(TARGET_SDL)
315 SDLFillRectangle(bitmap, x, y, width, height, color);
317 X11FillRectangle(bitmap, x, y, width, height, color);
321 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
322 int src_x, int src_y, int width, int height,
323 int dst_x, int dst_y, int mask_mode)
325 #if defined(TARGET_SDL)
326 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
327 dst_x, dst_y, mask_mode);
329 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
330 dst_x, dst_y, mask_mode);
334 void InitVideoDisplay(void)
336 #if defined(TARGET_SDL)
337 SDLInitVideoDisplay();
339 X11InitVideoDisplay();
343 void CloseVideoDisplay(void)
345 KeyboardAutoRepeatOn();
347 #if defined(TARGET_SDL)
348 SDL_QuitSubSystem(SDL_INIT_VIDEO);
351 XCloseDisplay(display);
355 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
358 video.height = height;
359 video.depth = GetRealDepth(depth);
361 video.fullscreen_available = FULLSCREEN_STATUS;
362 video.fullscreen_enabled = FALSE;
363 video.fullscreen_modes = NULL;
364 video.fullscreen_mode_current = NULL;
366 #if defined(TARGET_SDL)
367 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
369 X11InitVideoBuffer(&backbuffer, &window);
375 Bitmap *CreateBitmapStruct(void)
377 #if defined(TARGET_SDL)
378 return checked_calloc(sizeof(struct SDLSurfaceInfo));
380 return checked_calloc(sizeof(struct X11DrawableInfo));
384 Bitmap *CreateBitmap(int width, int height, int depth)
386 Bitmap *new_bitmap = CreateBitmapStruct();
387 int real_depth = GetRealDepth(depth);
389 #if defined(TARGET_SDL)
390 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
392 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
395 new_bitmap->width = width;
396 new_bitmap->height = height;
401 inline static void FreeBitmapPointers(Bitmap *bitmap)
406 #if defined(TARGET_SDL)
407 SDLFreeBitmapPointers(bitmap);
409 X11FreeBitmapPointers(bitmap);
412 checked_free(bitmap->source_filename);
413 bitmap->source_filename = NULL;
416 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
419 if (src_bitmap == NULL || dst_bitmap == NULL)
422 FreeBitmapPointers(dst_bitmap);
424 *dst_bitmap = *src_bitmap;
427 void FreeBitmap(Bitmap *bitmap)
432 FreeBitmapPointers(bitmap);
437 void CloseWindow(DrawWindow *window)
439 #if defined(TARGET_X11)
440 if (window->drawable)
442 XUnmapWindow(display, window->drawable);
443 XDestroyWindow(display, window->drawable);
446 XFreeGC(display, window->gc);
450 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
453 if (draw_mask == REDRAW_NONE)
456 if (draw_mask & REDRAW_ALL)
459 if ((draw_mask & REDRAW_FIELD) &&
460 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
463 if ((draw_mask & REDRAW_DOOR_1) &&
464 x >= gfx.dx && y < gfx.dy + gfx.dysize)
467 if ((draw_mask & REDRAW_DOOR_2) &&
468 x >= gfx.dx && y >= gfx.vy)
474 boolean DrawingDeactivated(int x, int y, int width, int height)
476 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
479 boolean DrawingOnBackground(int x, int y)
481 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
482 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
485 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
486 int src_x, int src_y, int width, int height,
487 int dst_x, int dst_y)
489 if (DrawingDeactivated(dst_x, dst_y, width, height))
492 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
493 dst_x, dst_y, BLIT_OPAQUE);
496 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
497 int fade_mode, int fade_delay, int post_delay,
498 void (*draw_border_function)(void))
500 #if defined(TARGET_SDL)
501 SDLFadeRectangle(bitmap_cross, x, y, width, height,
502 fade_mode, fade_delay, post_delay, draw_border_function);
504 X11FadeRectangle(bitmap_cross, x, y, width, height,
505 fade_mode, fade_delay, post_delay, draw_border_function);
509 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
512 if (DrawingDeactivated(x, y, width, height))
515 sysFillRectangle(bitmap, x, y, width, height, color);
518 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
520 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
523 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
524 int width, int height)
526 if (DrawingOnBackground(x, y))
527 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
529 ClearRectangle(bitmap, x, y, width, height);
532 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
534 #if defined(TARGET_X11)
537 bitmap->clip_gc = clip_gc;
538 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
543 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
545 #if defined(TARGET_X11)
548 bitmap->clip_gc = clip_gc;
549 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
554 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
555 int src_x, int src_y, int width, int height,
556 int dst_x, int dst_y)
558 if (DrawingDeactivated(dst_x, dst_y, width, height))
561 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
562 dst_x, dst_y, BLIT_MASKED);
565 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
566 int src_x, int src_y, int width, int height,
567 int dst_x, int dst_y)
569 if (DrawingOnBackground(dst_x, dst_y))
571 /* draw background */
572 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
575 /* draw foreground */
576 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
577 dst_x - src_x, dst_y - src_y);
578 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
582 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
586 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
589 #if defined(TARGET_SDL)
590 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
592 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
596 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
599 #if defined(TARGET_SDL)
600 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
602 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
606 #if !defined(TARGET_X11_NATIVE)
607 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
608 int to_x, int to_y, Pixel pixel, int line_width)
612 for (x = 0; x < line_width; x++)
614 for (y = 0; y < line_width; y++)
616 int dx = x - line_width / 2;
617 int dy = y - line_width / 2;
619 if ((x == 0 && y == 0) ||
620 (x == 0 && y == line_width - 1) ||
621 (x == line_width - 1 && y == 0) ||
622 (x == line_width - 1 && y == line_width - 1))
625 #if defined(TARGET_SDL)
627 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
628 #elif defined(TARGET_ALLEGRO)
629 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
630 to_x + dx, to_y + dy, pixel);
637 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
639 #if !defined(TARGET_X11_NATIVE)
643 for (i = 0; i < num_points - 1; i++)
644 DrawLine(bitmap, points[i].x, points[i].y,
645 points[i + 1].x, points[i + 1].y, pixel, line_width);
648 SDLDrawLines(bitmap->surface, points, num_points, pixel);
651 XSetForeground(display, bitmap->line_gc[1], pixel);
652 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
653 (XPoint *)points, num_points, CoordModeOrigin);
657 Pixel GetPixel(Bitmap *bitmap, int x, int y)
659 if (x < 0 || x >= bitmap->width ||
660 y < 0 || y >= bitmap->height)
663 #if defined(TARGET_SDL)
664 return SDLGetPixel(bitmap, x, y);
665 #elif defined(TARGET_ALLEGRO)
666 return AllegroGetPixel(bitmap->drawable, x, y);
668 return X11GetPixel(bitmap, x, y);
672 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
673 unsigned int color_g, unsigned int color_b)
675 #if defined(TARGET_SDL)
676 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
677 #elif defined(TARGET_ALLEGRO)
678 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
680 return X11GetPixelFromRGB(color_r, color_g, color_b);
684 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
686 unsigned int color_r = (color >> 16) & 0xff;
687 unsigned int color_g = (color >> 8) & 0xff;
688 unsigned int color_b = (color >> 0) & 0xff;
690 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
693 /* execute all pending screen drawing operations */
694 void FlushDisplay(void)
701 /* execute and wait for all pending screen drawing operations */
702 void SyncDisplay(void)
705 XSync(display, FALSE);
709 void KeyboardAutoRepeatOn(void)
711 #if defined(TARGET_SDL)
712 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
713 SDL_DEFAULT_REPEAT_INTERVAL / 2);
714 SDL_EnableUNICODE(1);
717 XAutoRepeatOn(display);
721 void KeyboardAutoRepeatOff(void)
723 #if defined(TARGET_SDL)
724 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
725 SDL_EnableUNICODE(0);
728 XAutoRepeatOff(display);
732 boolean PointerInWindow(DrawWindow *window)
734 #if defined(TARGET_SDL)
742 /* if XQueryPointer() returns False, the pointer
743 is not on the same screen as the specified window */
744 return XQueryPointer(display, window->drawable, &root, &child,
745 &root_x, &root_y, &win_x, &win_y, &mask);
749 boolean SetVideoMode(boolean fullscreen)
751 #if defined(TARGET_SDL)
752 return SDLSetVideoMode(&backbuffer, fullscreen);
754 boolean success = TRUE;
756 if (fullscreen && video.fullscreen_available)
758 Error(ERR_WARN, "fullscreen not available in X11 version");
760 /* display error message only once */
761 video.fullscreen_available = FALSE;
770 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
772 #if defined(TARGET_SDL)
773 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
774 (!fullscreen && video.fullscreen_enabled))
775 fullscreen = SetVideoMode(fullscreen);
781 Bitmap *LoadImage(char *filename)
785 #if defined(TARGET_SDL)
786 new_bitmap = SDLLoadImage(filename);
788 new_bitmap = X11LoadImage(filename);
792 new_bitmap->source_filename = getStringCopy(filename);
797 Bitmap *LoadCustomImage(char *basename)
799 char *filename = getCustomImageFilename(basename);
802 if (filename == NULL)
803 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
805 if ((new_bitmap = LoadImage(filename)) == NULL)
806 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
811 void ReloadCustomImage(Bitmap *bitmap, char *basename)
813 char *filename = getCustomImageFilename(basename);
816 if (filename == NULL) /* (should never happen) */
818 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
822 if (strEqual(filename, bitmap->source_filename))
824 /* The old and new image are the same (have the same filename and path).
825 This usually means that this image does not exist in this graphic set
826 and a fallback to the existing image is done. */
831 if ((new_bitmap = LoadImage(filename)) == NULL)
833 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
837 if (bitmap->width != new_bitmap->width ||
838 bitmap->height != new_bitmap->height)
840 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
842 FreeBitmap(new_bitmap);
846 TransferBitmapPointers(new_bitmap, bitmap);
850 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
852 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
854 #if defined(TARGET_SDL)
855 SDLZoomBitmap(src_bitmap, dst_bitmap);
857 X11ZoomBitmap(src_bitmap, dst_bitmap);
863 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
864 boolean create_small_bitmaps)
868 Bitmap *tmp_bitmap_1;
869 Bitmap *tmp_bitmap_2;
870 Bitmap *tmp_bitmap_4;
871 Bitmap *tmp_bitmap_8;
872 Bitmap *tmp_bitmap_16;
873 Bitmap *tmp_bitmap_32;
874 int width_1, height_1;
875 int width_2, height_2;
876 int width_4, height_4;
877 int width_8, height_8;
878 int width_16, height_16;
879 int width_32, height_32;
880 int new_width, new_height;
882 /* calculate new image dimensions for normal sized image */
883 width_1 = old_bitmap->width * zoom_factor;
884 height_1 = old_bitmap->height * zoom_factor;
886 /* get image with normal size (this might require scaling up) */
887 if (zoom_factor != 1)
888 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
890 tmp_bitmap_1 = old_bitmap;
892 /* this is only needed to make compilers happy */
896 tmp_bitmap_16 = NULL;
897 tmp_bitmap_32 = NULL;
899 if (create_small_bitmaps)
901 /* calculate new image dimensions for small images */
902 width_2 = width_1 / 2;
903 height_2 = height_1 / 2;
904 width_4 = width_1 / 4;
905 height_4 = height_1 / 4;
906 width_8 = width_1 / 8;
907 height_8 = height_1 / 8;
908 width_16 = width_1 / 16;
909 height_16 = height_1 / 16;
910 width_32 = width_1 / 32;
911 height_32 = height_1 / 32;
915 /* get image with 1/2 of normal size (for use in the level editor) */
916 if (zoom_factor != 2)
917 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
919 tmp_bitmap_2 = old_bitmap;
923 /* get image with 1/4 of normal size (for use in the level editor) */
924 if (zoom_factor != 4)
925 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
927 tmp_bitmap_4 = old_bitmap;
931 /* get image with 1/8 of normal size (for use on the preview screen) */
932 if (zoom_factor != 8)
933 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
935 tmp_bitmap_8 = old_bitmap;
939 /* get image with 1/16 of normal size (for use on the preview screen) */
940 if (zoom_factor != 16)
941 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
943 tmp_bitmap_16 = old_bitmap;
947 /* get image with 1/32 of normal size (for use on the preview screen) */
948 if (zoom_factor != 32)
949 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
951 tmp_bitmap_32 = old_bitmap;
957 /* if image was scaled up, create new clipmask for normal size image */
958 if (zoom_factor != 1)
960 #if defined(TARGET_X11)
961 if (old_bitmap->clip_mask)
962 XFreePixmap(display, old_bitmap->clip_mask);
964 old_bitmap->clip_mask =
965 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
967 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
969 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
971 if (old_bitmap->surface_masked)
972 SDL_FreeSurface(old_bitmap->surface_masked);
974 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
975 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
976 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
977 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
978 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
983 if (create_small_bitmaps)
986 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
988 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
990 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
991 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
993 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
994 width_1 / 2, height_1);
995 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
996 3 * width_1 / 4, height_1);
997 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
998 7 * width_1 / 8, height_1);
999 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1000 15 * width_1 / 16, height_1);
1002 UPDATE_BUSY_STATE();
1006 new_width = width_1;
1007 new_height = height_1;
1009 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1012 if (create_small_bitmaps)
1014 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1015 if (zoom_factor != 1)
1016 FreeBitmap(tmp_bitmap_1);
1018 if (zoom_factor != 2)
1019 FreeBitmap(tmp_bitmap_2);
1021 if (zoom_factor != 4)
1022 FreeBitmap(tmp_bitmap_4);
1024 if (zoom_factor != 8)
1025 FreeBitmap(tmp_bitmap_8);
1027 if (zoom_factor != 16)
1028 FreeBitmap(tmp_bitmap_16);
1030 if (zoom_factor != 32)
1031 FreeBitmap(tmp_bitmap_32);
1034 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1035 #if defined(TARGET_SDL)
1036 swap_bitmap.surface = old_bitmap->surface;
1037 old_bitmap->surface = new_bitmap->surface;
1038 new_bitmap->surface = swap_bitmap.surface;
1040 swap_bitmap.drawable = old_bitmap->drawable;
1041 old_bitmap->drawable = new_bitmap->drawable;
1042 new_bitmap->drawable = swap_bitmap.drawable;
1045 old_bitmap->width = new_bitmap->width;
1046 old_bitmap->height = new_bitmap->height;
1049 /* this replaces all blit masks created when loading -- maybe optimize this */
1051 #if defined(TARGET_X11)
1052 if (old_bitmap->clip_mask)
1053 XFreePixmap(display, old_bitmap->clip_mask);
1055 old_bitmap->clip_mask =
1056 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1058 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1060 SDL_Surface *old_surface = old_bitmap->surface;
1062 if (old_bitmap->surface_masked)
1063 SDL_FreeSurface(old_bitmap->surface_masked);
1065 SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
1066 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1067 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1068 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1069 SDL_SetColorKey(old_surface, 0, 0); /* reset transparent pixel */
1074 UPDATE_BUSY_STATE();
1076 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1079 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1081 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1084 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1086 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1090 /* ------------------------------------------------------------------------- */
1091 /* mouse pointer functions */
1092 /* ------------------------------------------------------------------------- */
1094 #if !defined(PLATFORM_MSDOS)
1095 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1096 /* XPM image definitions */
1097 static const char *cursor_image_none[] =
1099 /* width height num_colors chars_per_pixel */
1128 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1129 static const char *cursor_image_dot[] =
1131 /* width height num_colors chars_per_pixel */
1160 static const char **cursor_image_playfield = cursor_image_dot;
1162 /* some people complained about a "white dot" on the screen and thought it
1163 was a graphical error... OK, let's just remove the whole pointer :-) */
1164 static const char **cursor_image_playfield = cursor_image_none;
1167 #if defined(TARGET_SDL)
1168 static const int cursor_bit_order = BIT_ORDER_MSB;
1169 #elif defined(TARGET_X11_NATIVE)
1170 static const int cursor_bit_order = BIT_ORDER_LSB;
1173 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1175 struct MouseCursorInfo *cursor;
1176 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1177 int header_lines = 4;
1180 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1182 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1185 for (y = 0; y < cursor->width; y++)
1187 for (x = 0; x < cursor->height; x++)
1190 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1195 cursor->data[i] = cursor->mask[i] = 0;
1198 switch (image[header_lines + y][x])
1201 cursor->data[i] |= bit_mask;
1202 cursor->mask[i] |= bit_mask;
1206 cursor->mask[i] |= bit_mask;
1215 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1219 #endif /* !PLATFORM_MSDOS */
1221 void SetMouseCursor(int mode)
1223 #if !defined(PLATFORM_MSDOS)
1224 static struct MouseCursorInfo *cursor_none = NULL;
1225 static struct MouseCursorInfo *cursor_playfield = NULL;
1226 struct MouseCursorInfo *cursor_new;
1228 if (cursor_none == NULL)
1229 cursor_none = get_cursor_from_image(cursor_image_none);
1231 if (cursor_playfield == NULL)
1232 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1234 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1235 mode == CURSOR_NONE ? cursor_none :
1236 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1238 #if defined(TARGET_SDL)
1239 SDLSetMouseCursor(cursor_new);
1240 #elif defined(TARGET_X11_NATIVE)
1241 X11SetMouseCursor(cursor_new);
1247 /* ========================================================================= */
1248 /* audio functions */
1249 /* ========================================================================= */
1251 void OpenAudio(void)
1253 /* always start with reliable default values */
1254 audio.sound_available = FALSE;
1255 audio.music_available = FALSE;
1256 audio.loops_available = FALSE;
1258 audio.sound_enabled = FALSE;
1259 audio.sound_deactivated = FALSE;
1261 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1262 audio.mixer_pid = 0;
1263 audio.device_name = NULL;
1264 audio.device_fd = -1;
1266 audio.num_channels = 0;
1267 audio.music_channel = 0;
1268 audio.first_sound_channel = 0;
1270 #if defined(TARGET_SDL)
1272 #elif defined(PLATFORM_UNIX)
1274 #elif defined(PLATFORM_MSDOS)
1279 void CloseAudio(void)
1281 #if defined(TARGET_SDL)
1283 #elif defined(PLATFORM_UNIX)
1285 #elif defined(PLATFORM_MSDOS)
1289 audio.sound_enabled = FALSE;
1292 void SetAudioMode(boolean enabled)
1294 if (!audio.sound_available)
1297 audio.sound_enabled = enabled;
1301 /* ========================================================================= */
1302 /* event functions */
1303 /* ========================================================================= */
1305 void InitEventFilter(EventFilter filter_function)
1307 #if defined(TARGET_SDL)
1308 /* set event filter to filter out certain events */
1309 SDL_SetEventFilter(filter_function);
1313 boolean PendingEvent(void)
1315 #if defined(TARGET_SDL)
1316 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1318 return (XPending(display) ? TRUE : FALSE);
1322 void NextEvent(Event *event)
1324 #if defined(TARGET_SDL)
1325 SDLNextEvent(event);
1327 XNextEvent(display, event);
1331 void PeekEvent(Event *event)
1333 #if defined(TARGET_SDL)
1334 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1336 XPeekEvent(display, event);
1340 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1342 #if defined(TARGET_SDL)
1345 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1346 (int)event->keysym.unicode,
1347 (int)event->keysym.sym,
1348 (int)SDL_GetModState());
1351 if (with_modifiers &&
1352 event->keysym.unicode > 0x0000 &&
1353 event->keysym.unicode < 0x2000)
1354 return event->keysym.unicode;
1356 return event->keysym.sym;
1361 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1362 (int)XLookupKeysym(event, event->state),
1363 (int)XLookupKeysym(event, 0));
1367 return XLookupKeysym(event, event->state);
1369 return XLookupKeysym(event, 0);
1373 KeyMod HandleKeyModState(Key key, int key_status)
1375 static KeyMod current_modifiers = KMOD_None;
1377 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1379 KeyMod new_modifier = KMOD_None;
1384 new_modifier = KMOD_Shift_L;
1387 new_modifier = KMOD_Shift_R;
1389 case KSYM_Control_L:
1390 new_modifier = KMOD_Control_L;
1392 case KSYM_Control_R:
1393 new_modifier = KMOD_Control_R;
1396 new_modifier = KMOD_Meta_L;
1399 new_modifier = KMOD_Meta_R;
1402 new_modifier = KMOD_Alt_L;
1405 new_modifier = KMOD_Alt_R;
1411 if (key_status == KEY_PRESSED)
1412 current_modifiers |= new_modifier;
1414 current_modifiers &= ~new_modifier;
1417 return current_modifiers;
1420 KeyMod GetKeyModState()
1422 #if defined(TARGET_SDL)
1423 return (KeyMod)SDL_GetModState();
1425 return HandleKeyModState(KSYM_UNDEFINED, 0);
1429 KeyMod GetKeyModStateFromEvents()
1431 /* always use key modifier state as tracked from key events (this is needed
1432 if the modifier key event was injected into the event queue, but the key
1433 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1434 query the keys as held pressed on the keyboard) -- this case is currently
1435 only used to filter out clipboard insert events from "True X-Mouse" tool */
1437 return HandleKeyModState(KSYM_UNDEFINED, 0);
1440 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1442 if (event->type != EVENT_CLIENTMESSAGE)
1445 #if defined(TARGET_SDL)
1446 return TRUE; /* the only possible message here is SDL_QUIT */
1447 #elif defined(PLATFORM_UNIX)
1448 if ((event->window == window->drawable) &&
1449 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1457 /* ========================================================================= */
1458 /* joystick functions */
1459 /* ========================================================================= */
1461 void InitJoysticks()
1465 #if defined(NO_JOYSTICK)
1466 return; /* joysticks generally deactivated by compile-time directive */
1469 /* always start with reliable default values */
1470 joystick.status = JOYSTICK_NOT_AVAILABLE;
1471 for (i = 0; i < MAX_PLAYERS; i++)
1472 joystick.fd[i] = -1; /* joystick device closed */
1474 #if defined(TARGET_SDL)
1476 #elif defined(PLATFORM_UNIX)
1477 UnixInitJoysticks();
1478 #elif defined(PLATFORM_MSDOS)
1479 MSDOSInitJoysticks();
1483 for (i = 0; i < MAX_PLAYERS; i++)
1484 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1488 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1490 #if defined(TARGET_SDL)
1491 return SDLReadJoystick(nr, x, y, b1, b2);
1492 #elif defined(PLATFORM_UNIX)
1493 return UnixReadJoystick(nr, x, y, b1, b2);
1494 #elif defined(PLATFORM_MSDOS)
1495 return MSDOSReadJoystick(nr, x, y, b1, b2);