1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
19 #if defined(PLATFORM_MSDOS)
31 /* ========================================================================= */
32 /* exported variables */
33 /* ========================================================================= */
35 struct ProgramInfo program;
36 struct OptionInfo options;
37 struct VideoSystemInfo video;
38 struct AudioSystemInfo audio;
40 struct ArtworkInfo artwork;
41 struct JoystickInfo joystick;
42 struct SetupInfo setup;
44 LevelDirTree *leveldir_first_all = NULL;
45 LevelDirTree *leveldir_first = NULL;
46 LevelDirTree *leveldir_current = NULL;
49 Display *display = NULL;
50 Visual *visual = NULL;
54 DrawWindow *window = NULL;
55 DrawBuffer *backbuffer = NULL;
56 DrawBuffer *drawto = NULL;
58 int button_status = MB_NOT_PRESSED;
59 boolean motion_status = FALSE;
61 int redraw_mask = REDRAW_NONE;
67 /* ========================================================================= */
68 /* init/close functions */
69 /* ========================================================================= */
71 void InitProgramInfo(char *argv0,
72 char *userdata_subdir, char *userdata_subdir_unix,
73 char *program_title, char *window_title, char *icon_title,
74 char *x11_icon_filename, char *x11_iconmask_filename,
75 char *sdl_icon_filename, char *msdos_cursor_filename,
76 char *cookie_prefix, char *filename_prefix,
79 program.command_basepath = getBasePath(argv0);
80 program.command_basename = getBaseName(argv0);
82 program.userdata_subdir = userdata_subdir;
83 program.userdata_subdir_unix = userdata_subdir_unix;
84 program.userdata_path = getUserGameDataDir();
86 program.program_title = program_title;
87 program.window_title = window_title;
88 program.icon_title = icon_title;
90 program.x11_icon_filename = x11_icon_filename;
91 program.x11_iconmask_filename = x11_iconmask_filename;
92 program.sdl_icon_filename = sdl_icon_filename;
93 program.msdos_cursor_filename = msdos_cursor_filename;
95 program.cookie_prefix = cookie_prefix;
96 program.filename_prefix = filename_prefix;
98 program.version_major = VERSION_MAJOR(program_version);
99 program.version_minor = VERSION_MINOR(program_version);
100 program.version_patch = VERSION_PATCH(program_version);
102 program.error_filename = getErrorFilename(ERROR_BASENAME);
103 program.error_file = stderr;
106 void InitExitFunction(void (*exit_function)(int))
108 program.exit_function = exit_function;
110 /* set signal handlers to custom exit function */
111 signal(SIGINT, exit_function);
112 signal(SIGTERM, exit_function);
114 #if defined(TARGET_SDL)
115 /* set exit function to automatically cleanup SDL stuff after exit() */
120 void InitPlatformDependentStuff(void)
122 #if defined(PLATFORM_MSDOS)
126 #if defined(PLATFORM_MACOSX)
127 updateUserGameDataDir();
130 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
134 #if defined(TARGET_SDL)
135 if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
136 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
142 void ClosePlatformDependentStuff(void)
144 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
148 #if defined(PLATFORM_MSDOS)
153 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
154 int real_sx, int real_sy,
155 int full_sxsize, int full_sysize,
156 Bitmap *field_save_buffer)
162 gfx.real_sx = real_sx;
163 gfx.real_sy = real_sy;
164 gfx.full_sxsize = full_sxsize;
165 gfx.full_sysize = full_sysize;
167 gfx.field_save_buffer = field_save_buffer;
169 gfx.background_bitmap = NULL;
170 gfx.background_bitmap_mask = REDRAW_NONE;
172 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
173 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
176 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
184 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
192 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
194 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
195 gfx.scrollbuffer_width = scrollbuffer_width;
196 gfx.scrollbuffer_height = scrollbuffer_height;
199 void SetDrawDeactivationMask(int draw_deactivation_mask)
201 gfx.draw_deactivation_mask = draw_deactivation_mask;
204 void SetDrawBackgroundMask(int draw_background_mask)
206 gfx.draw_background_mask = draw_background_mask;
209 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
210 int dest_x, int dest_y, int width, int height)
212 int bitmap_xsize = width;
213 int bitmap_ysize = height;
214 int tile_xsize = tile->width;
215 int tile_ysize = tile->height;
216 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
217 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
220 for (y = 0; y < tile_ysteps; y++)
222 for (x = 0; x < tile_xsteps; x++)
224 int draw_x = dest_x + x * tile_xsize;
225 int draw_y = dest_y + y * tile_ysize;
226 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
227 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
229 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
234 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
236 if (background_bitmap_tile != NULL)
237 gfx.background_bitmap_mask |= mask;
239 gfx.background_bitmap_mask &= ~mask;
241 if (gfx.background_bitmap == NULL)
242 gfx.background_bitmap = CreateBitmap(video.width, video.height,
245 if (background_bitmap_tile == NULL) /* empty background requested */
248 if (mask == REDRAW_ALL)
249 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
250 0, 0, video.width, video.height);
251 else if (mask == REDRAW_FIELD)
252 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
253 gfx.real_sx, gfx.real_sy,
254 gfx.full_sxsize, gfx.full_sysize);
255 else if (mask == REDRAW_DOOR_1)
257 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
259 gfx.dxsize, gfx.dysize);
263 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
265 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
268 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
270 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
271 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
274 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
276 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
277 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
281 /* ========================================================================= */
282 /* video functions */
283 /* ========================================================================= */
285 inline static int GetRealDepth(int depth)
287 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
290 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
291 int width, int height, Pixel color)
293 #if defined(TARGET_SDL)
294 SDLFillRectangle(bitmap, x, y, width, height, color);
296 X11FillRectangle(bitmap, x, y, width, height, color);
300 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
301 int src_x, int src_y, int width, int height,
302 int dst_x, int dst_y, int mask_mode)
304 #if defined(TARGET_SDL)
305 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
306 dst_x, dst_y, mask_mode);
308 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
309 dst_x, dst_y, mask_mode);
313 void InitVideoDisplay(void)
315 #if defined(TARGET_SDL)
316 SDLInitVideoDisplay();
318 X11InitVideoDisplay();
322 void CloseVideoDisplay(void)
324 KeyboardAutoRepeatOn();
326 #if defined(TARGET_SDL)
327 SDL_QuitSubSystem(SDL_INIT_VIDEO);
330 XCloseDisplay(display);
334 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
337 video.height = height;
338 video.depth = GetRealDepth(depth);
340 video.fullscreen_available = FULLSCREEN_STATUS;
341 video.fullscreen_enabled = FALSE;
342 video.fullscreen_modes = NULL;
343 video.fullscreen_mode_current = NULL;
345 #if defined(TARGET_SDL)
346 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
348 X11InitVideoBuffer(&backbuffer, &window);
354 Bitmap *CreateBitmapStruct(void)
356 #if defined(TARGET_SDL)
357 return checked_calloc(sizeof(struct SDLSurfaceInfo));
359 return checked_calloc(sizeof(struct X11DrawableInfo));
363 Bitmap *CreateBitmap(int width, int height, int depth)
365 Bitmap *new_bitmap = CreateBitmapStruct();
366 int real_depth = GetRealDepth(depth);
368 #if defined(TARGET_SDL)
369 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
371 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
374 new_bitmap->width = width;
375 new_bitmap->height = height;
380 inline static void FreeBitmapPointers(Bitmap *bitmap)
385 #if defined(TARGET_SDL)
386 SDLFreeBitmapPointers(bitmap);
388 X11FreeBitmapPointers(bitmap);
391 checked_free(bitmap->source_filename);
392 bitmap->source_filename = NULL;
395 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
398 if (src_bitmap == NULL || dst_bitmap == NULL)
401 FreeBitmapPointers(dst_bitmap);
403 *dst_bitmap = *src_bitmap;
406 void FreeBitmap(Bitmap *bitmap)
411 FreeBitmapPointers(bitmap);
416 void CloseWindow(DrawWindow *window)
418 #if defined(TARGET_X11)
419 if (window->drawable)
421 XUnmapWindow(display, window->drawable);
422 XDestroyWindow(display, window->drawable);
425 XFreeGC(display, window->gc);
429 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
432 if (draw_mask == REDRAW_NONE)
435 if (draw_mask & REDRAW_ALL)
438 if ((draw_mask & REDRAW_FIELD) &&
439 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
442 if ((draw_mask & REDRAW_DOOR_1) &&
443 x >= gfx.dx && y < gfx.dy + gfx.dysize)
446 if ((draw_mask & REDRAW_DOOR_2) &&
447 x >= gfx.dx && y >= gfx.vy)
453 boolean DrawingDeactivated(int x, int y, int width, int height)
455 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
458 boolean DrawingOnBackground(int x, int y)
460 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
461 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
464 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
465 int src_x, int src_y, int width, int height,
466 int dst_x, int dst_y)
468 if (DrawingDeactivated(dst_x, dst_y, width, height))
471 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
472 dst_x, dst_y, BLIT_OPAQUE);
475 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
476 int fade_mode, int fade_delay, int post_delay,
477 void (*draw_border_function)(void))
479 #if defined(TARGET_SDL)
480 SDLFadeRectangle(bitmap_cross, x, y, width, height,
481 fade_mode, fade_delay, post_delay, draw_border_function);
483 X11FadeRectangle(bitmap_cross, x, y, width, height,
484 fade_mode, fade_delay, post_delay, draw_border_function);
488 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
491 if (DrawingDeactivated(x, y, width, height))
494 sysFillRectangle(bitmap, x, y, width, height, color);
497 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
499 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
502 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
503 int width, int height)
505 if (DrawingOnBackground(x, y))
506 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
508 ClearRectangle(bitmap, x, y, width, height);
511 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
513 #if defined(TARGET_X11)
516 bitmap->clip_gc = clip_gc;
517 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
522 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
524 #if defined(TARGET_X11)
527 bitmap->clip_gc = clip_gc;
528 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
533 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
534 int src_x, int src_y, int width, int height,
535 int dst_x, int dst_y)
537 if (DrawingDeactivated(dst_x, dst_y, width, height))
540 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
541 dst_x, dst_y, BLIT_MASKED);
544 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
545 int src_x, int src_y, int width, int height,
546 int dst_x, int dst_y)
548 if (DrawingOnBackground(dst_x, dst_y))
550 /* draw background */
551 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
554 /* draw foreground */
555 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
556 dst_x - src_x, dst_y - src_y);
557 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
561 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
565 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
568 #if defined(TARGET_SDL)
569 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
571 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
575 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
578 #if defined(TARGET_SDL)
579 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
581 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
585 #if !defined(TARGET_X11_NATIVE)
586 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
587 int to_x, int to_y, Pixel pixel, int line_width)
591 for (x = 0; x < line_width; x++)
593 for (y = 0; y < line_width; y++)
595 int dx = x - line_width / 2;
596 int dy = y - line_width / 2;
598 if ((x == 0 && y == 0) ||
599 (x == 0 && y == line_width - 1) ||
600 (x == line_width - 1 && y == 0) ||
601 (x == line_width - 1 && y == line_width - 1))
604 #if defined(TARGET_SDL)
606 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
607 #elif defined(TARGET_ALLEGRO)
608 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
609 to_x + dx, to_y + dy, pixel);
616 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
618 #if !defined(TARGET_X11_NATIVE)
622 for (i = 0; i < num_points - 1; i++)
623 DrawLine(bitmap, points[i].x, points[i].y,
624 points[i + 1].x, points[i + 1].y, pixel, line_width);
627 SDLDrawLines(bitmap->surface, points, num_points, pixel);
630 XSetForeground(display, bitmap->line_gc[1], pixel);
631 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
632 (XPoint *)points, num_points, CoordModeOrigin);
636 Pixel GetPixel(Bitmap *bitmap, int x, int y)
638 if (x < 0 || x >= bitmap->width ||
639 y < 0 || y >= bitmap->height)
642 #if defined(TARGET_SDL)
643 return SDLGetPixel(bitmap, x, y);
644 #elif defined(TARGET_ALLEGRO)
645 return AllegroGetPixel(bitmap->drawable, x, y);
647 return X11GetPixel(bitmap, x, y);
651 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
652 unsigned int color_g, unsigned int color_b)
654 #if defined(TARGET_SDL)
655 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
656 #elif defined(TARGET_ALLEGRO)
657 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
659 return X11GetPixelFromRGB(color_r, color_g, color_b);
663 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
665 unsigned int color_r = (color >> 16) & 0xff;
666 unsigned int color_g = (color >> 8) & 0xff;
667 unsigned int color_b = (color >> 0) & 0xff;
669 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
672 /* execute all pending screen drawing operations */
673 void FlushDisplay(void)
680 /* execute and wait for all pending screen drawing operations */
681 void SyncDisplay(void)
684 XSync(display, FALSE);
688 void KeyboardAutoRepeatOn(void)
690 #if defined(TARGET_SDL)
691 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
692 SDL_DEFAULT_REPEAT_INTERVAL / 2);
693 SDL_EnableUNICODE(1);
696 XAutoRepeatOn(display);
700 void KeyboardAutoRepeatOff(void)
702 #if defined(TARGET_SDL)
703 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
704 SDL_EnableUNICODE(0);
707 XAutoRepeatOff(display);
711 boolean PointerInWindow(DrawWindow *window)
713 #if defined(TARGET_SDL)
721 /* if XQueryPointer() returns False, the pointer
722 is not on the same screen as the specified window */
723 return XQueryPointer(display, window->drawable, &root, &child,
724 &root_x, &root_y, &win_x, &win_y, &mask);
728 boolean SetVideoMode(boolean fullscreen)
730 #if defined(TARGET_SDL)
731 return SDLSetVideoMode(&backbuffer, fullscreen);
733 boolean success = TRUE;
735 if (fullscreen && video.fullscreen_available)
737 Error(ERR_WARN, "fullscreen not available in X11 version");
739 /* display error message only once */
740 video.fullscreen_available = FALSE;
749 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
751 #if defined(TARGET_SDL)
752 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
753 (!fullscreen && video.fullscreen_enabled))
754 fullscreen = SetVideoMode(fullscreen);
760 Bitmap *LoadImage(char *filename)
764 #if defined(TARGET_SDL)
765 new_bitmap = SDLLoadImage(filename);
767 new_bitmap = X11LoadImage(filename);
771 new_bitmap->source_filename = getStringCopy(filename);
776 Bitmap *LoadCustomImage(char *basename)
778 char *filename = getCustomImageFilename(basename);
781 if (filename == NULL)
782 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
784 if ((new_bitmap = LoadImage(filename)) == NULL)
785 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
790 void ReloadCustomImage(Bitmap *bitmap, char *basename)
792 char *filename = getCustomImageFilename(basename);
795 if (filename == NULL) /* (should never happen) */
797 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
801 if (strEqual(filename, bitmap->source_filename))
803 /* The old and new image are the same (have the same filename and path).
804 This usually means that this image does not exist in this graphic set
805 and a fallback to the existing image is done. */
810 if ((new_bitmap = LoadImage(filename)) == NULL)
812 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
816 if (bitmap->width != new_bitmap->width ||
817 bitmap->height != new_bitmap->height)
819 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
821 FreeBitmap(new_bitmap);
825 TransferBitmapPointers(new_bitmap, bitmap);
829 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
831 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
833 #if defined(TARGET_SDL)
834 SDLZoomBitmap(src_bitmap, dst_bitmap);
836 X11ZoomBitmap(src_bitmap, dst_bitmap);
844 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
845 boolean create_small_bitmaps)
850 Bitmap *tmp_bitmap_1;
851 Bitmap *tmp_bitmap_2;
852 Bitmap *tmp_bitmap_4;
853 Bitmap *tmp_bitmap_8;
854 Bitmap *tmp_bitmap_16;
855 Bitmap *tmp_bitmap_32;
856 int width_1, height_1;
857 int width_2, height_2;
858 int width_4, height_4;
859 int width_8, height_8;
860 int width_16, height_16;
861 int width_32, height_32;
863 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
864 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
866 int new_width, new_height;
868 /* calculate new image dimensions for normal sized image */
869 width_1 = old_bitmap->width * zoom_factor;
870 height_1 = old_bitmap->height * zoom_factor;
872 /* get image with normal size (this might require scaling up) */
873 if (zoom_factor != 1)
874 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
876 tmp_bitmap_1 = old_bitmap;
878 /* this is only needed to make compilers happy */
880 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = tmp_bitmap_16 = NULL;
881 tmp_bitmap_32 = NULL;
883 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
886 if (create_small_bitmaps)
888 /* calculate new image dimensions for small images */
889 width_2 = width_1 / 2;
890 height_2 = height_1 / 2;
891 width_4 = width_1 / 4;
892 height_4 = height_1 / 4;
893 width_8 = width_1 / 8;
894 height_8 = height_1 / 8;
896 width_16 = width_1 / 16;
897 height_16 = height_1 / 16;
898 width_32 = width_1 / 32;
899 height_32 = height_1 / 32;
902 /* get image with 1/2 of normal size (for use in the level editor) */
903 if (zoom_factor != 2)
904 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
906 tmp_bitmap_2 = old_bitmap;
908 /* get image with 1/4 of normal size (for use in the level editor) */
909 if (zoom_factor != 4)
910 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
912 tmp_bitmap_4 = old_bitmap;
914 /* get image with 1/8 of normal size (for use on the preview screen) */
915 if (zoom_factor != 8)
916 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
918 tmp_bitmap_8 = old_bitmap;
921 /* get image with 1/16 of normal size (for use on the preview screen) */
922 if (zoom_factor != 16)
923 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
925 tmp_bitmap_16 = old_bitmap;
927 /* get image with 1/32 of normal size (for use on the preview screen) */
928 if (zoom_factor != 32)
929 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
931 tmp_bitmap_32 = old_bitmap;
935 /* if image was scaled up, create new clipmask for normal size image */
936 if (zoom_factor != 1)
938 #if defined(TARGET_X11)
939 if (old_bitmap->clip_mask)
940 XFreePixmap(display, old_bitmap->clip_mask);
942 old_bitmap->clip_mask =
943 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
945 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
947 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
949 if (old_bitmap->surface_masked)
950 SDL_FreeSurface(old_bitmap->surface_masked);
952 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
953 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
954 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
955 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
956 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
960 if (create_small_bitmaps)
963 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
965 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
967 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
968 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
970 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
971 width_1 / 2, height_1);
972 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
973 3 * width_1 / 4, height_1);
975 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
976 7 * width_1 / 8, height_1);
977 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
978 15 * width_1 / 16, height_1);
984 new_height = height_1;
986 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
989 if (create_small_bitmaps)
991 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
992 if (zoom_factor != 1)
993 FreeBitmap(tmp_bitmap_1);
995 if (zoom_factor != 2)
996 FreeBitmap(tmp_bitmap_2);
998 if (zoom_factor != 4)
999 FreeBitmap(tmp_bitmap_4);
1001 if (zoom_factor != 8)
1002 FreeBitmap(tmp_bitmap_8);
1005 if (zoom_factor != 16)
1006 FreeBitmap(tmp_bitmap_16);
1007 if (zoom_factor != 32)
1008 FreeBitmap(tmp_bitmap_32);
1012 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1013 #if defined(TARGET_SDL)
1014 swap_bitmap.surface = old_bitmap->surface;
1015 old_bitmap->surface = new_bitmap->surface;
1016 new_bitmap->surface = swap_bitmap.surface;
1018 swap_bitmap.drawable = old_bitmap->drawable;
1019 old_bitmap->drawable = new_bitmap->drawable;
1020 new_bitmap->drawable = swap_bitmap.drawable;
1023 old_bitmap->width = new_bitmap->width;
1024 old_bitmap->height = new_bitmap->height;
1027 /* !!! THIS URGENTLY NEEDS OPTIMIZATION -- DO NOT CREATE MASKS BEFORE !!! */
1029 #if defined(TARGET_X11)
1030 if (old_bitmap->clip_mask)
1031 XFreePixmap(display, old_bitmap->clip_mask);
1033 old_bitmap->clip_mask =
1034 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1036 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1038 SDL_Surface *old_surface = old_bitmap->surface;
1040 if (old_bitmap->surface_masked)
1041 SDL_FreeSurface(old_bitmap->surface_masked);
1043 SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
1044 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1045 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1046 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1047 SDL_SetColorKey(old_surface, 0, 0); /* reset transparent pixel */
1052 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1055 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1057 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1060 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1062 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1066 /* ------------------------------------------------------------------------- */
1067 /* mouse pointer functions */
1068 /* ------------------------------------------------------------------------- */
1070 #if !defined(PLATFORM_MSDOS)
1071 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1072 /* XPM image definitions */
1073 static const char *cursor_image_none[] =
1075 /* width height num_colors chars_per_pixel */
1104 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1105 static const char *cursor_image_dot[] =
1107 /* width height num_colors chars_per_pixel */
1136 static const char **cursor_image_playfield = cursor_image_dot;
1138 /* some people complained about a "white dot" on the screen and thought it
1139 was a graphical error... OK, let's just remove the whole pointer :-) */
1140 static const char **cursor_image_playfield = cursor_image_none;
1143 #if defined(TARGET_SDL)
1144 static const int cursor_bit_order = BIT_ORDER_MSB;
1145 #elif defined(TARGET_X11_NATIVE)
1146 static const int cursor_bit_order = BIT_ORDER_LSB;
1149 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1151 struct MouseCursorInfo *cursor;
1152 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1153 int header_lines = 4;
1156 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1158 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1161 for (y = 0; y < cursor->width; y++)
1163 for (x = 0; x < cursor->height; x++)
1166 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1171 cursor->data[i] = cursor->mask[i] = 0;
1174 switch (image[header_lines + y][x])
1177 cursor->data[i] |= bit_mask;
1178 cursor->mask[i] |= bit_mask;
1182 cursor->mask[i] |= bit_mask;
1191 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1195 #endif /* !PLATFORM_MSDOS */
1197 void SetMouseCursor(int mode)
1199 #if !defined(PLATFORM_MSDOS)
1200 static struct MouseCursorInfo *cursor_none = NULL;
1201 static struct MouseCursorInfo *cursor_playfield = NULL;
1202 struct MouseCursorInfo *cursor_new;
1204 if (cursor_none == NULL)
1205 cursor_none = get_cursor_from_image(cursor_image_none);
1207 if (cursor_playfield == NULL)
1208 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1210 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1211 mode == CURSOR_NONE ? cursor_none :
1212 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1214 #if defined(TARGET_SDL)
1215 SDLSetMouseCursor(cursor_new);
1216 #elif defined(TARGET_X11_NATIVE)
1217 X11SetMouseCursor(cursor_new);
1223 /* ========================================================================= */
1224 /* audio functions */
1225 /* ========================================================================= */
1227 void OpenAudio(void)
1229 /* always start with reliable default values */
1230 audio.sound_available = FALSE;
1231 audio.music_available = FALSE;
1232 audio.loops_available = FALSE;
1234 audio.sound_enabled = FALSE;
1235 audio.sound_deactivated = FALSE;
1237 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1238 audio.mixer_pid = 0;
1239 audio.device_name = NULL;
1240 audio.device_fd = -1;
1242 audio.num_channels = 0;
1243 audio.music_channel = 0;
1244 audio.first_sound_channel = 0;
1246 #if defined(TARGET_SDL)
1248 #elif defined(PLATFORM_UNIX)
1250 #elif defined(PLATFORM_MSDOS)
1255 void CloseAudio(void)
1257 #if defined(TARGET_SDL)
1259 #elif defined(PLATFORM_UNIX)
1261 #elif defined(PLATFORM_MSDOS)
1265 audio.sound_enabled = FALSE;
1268 void SetAudioMode(boolean enabled)
1270 if (!audio.sound_available)
1273 audio.sound_enabled = enabled;
1277 /* ========================================================================= */
1278 /* event functions */
1279 /* ========================================================================= */
1281 void InitEventFilter(EventFilter filter_function)
1283 #if defined(TARGET_SDL)
1284 /* set event filter to filter out certain events */
1285 SDL_SetEventFilter(filter_function);
1289 boolean PendingEvent(void)
1291 #if defined(TARGET_SDL)
1292 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1294 return (XPending(display) ? TRUE : FALSE);
1298 void NextEvent(Event *event)
1300 #if defined(TARGET_SDL)
1301 SDLNextEvent(event);
1303 XNextEvent(display, event);
1307 void PeekEvent(Event *event)
1309 #if defined(TARGET_SDL)
1310 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1312 XPeekEvent(display, event);
1316 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1318 #if defined(TARGET_SDL)
1321 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1322 (int)event->keysym.unicode,
1323 (int)event->keysym.sym,
1324 (int)SDL_GetModState());
1327 if (with_modifiers &&
1328 event->keysym.unicode > 0x0000 &&
1329 event->keysym.unicode < 0x2000)
1330 return event->keysym.unicode;
1332 return event->keysym.sym;
1337 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1338 (int)XLookupKeysym(event, event->state),
1339 (int)XLookupKeysym(event, 0));
1343 return XLookupKeysym(event, event->state);
1345 return XLookupKeysym(event, 0);
1349 KeyMod HandleKeyModState(Key key, int key_status)
1351 static KeyMod current_modifiers = KMOD_None;
1353 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1355 KeyMod new_modifier = KMOD_None;
1360 new_modifier = KMOD_Shift_L;
1363 new_modifier = KMOD_Shift_R;
1365 case KSYM_Control_L:
1366 new_modifier = KMOD_Control_L;
1368 case KSYM_Control_R:
1369 new_modifier = KMOD_Control_R;
1372 new_modifier = KMOD_Meta_L;
1375 new_modifier = KMOD_Meta_R;
1378 new_modifier = KMOD_Alt_L;
1381 new_modifier = KMOD_Alt_R;
1387 if (key_status == KEY_PRESSED)
1388 current_modifiers |= new_modifier;
1390 current_modifiers &= ~new_modifier;
1393 return current_modifiers;
1396 KeyMod GetKeyModState()
1398 #if defined(TARGET_SDL)
1399 return (KeyMod)SDL_GetModState();
1401 return HandleKeyModState(KSYM_UNDEFINED, 0);
1405 KeyMod GetKeyModStateFromEvents()
1407 /* always use key modifier state as tracked from key events (this is needed
1408 if the modifier key event was injected into the event queue, but the key
1409 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1410 query the keys as held pressed on the keyboard) -- this case is currently
1411 only used to filter out clipboard insert events from "True X-Mouse" tool */
1413 return HandleKeyModState(KSYM_UNDEFINED, 0);
1416 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1418 if (event->type != EVENT_CLIENTMESSAGE)
1421 #if defined(TARGET_SDL)
1422 return TRUE; /* the only possible message here is SDL_QUIT */
1423 #elif defined(PLATFORM_UNIX)
1424 if ((event->window == window->drawable) &&
1425 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1433 /* ========================================================================= */
1434 /* joystick functions */
1435 /* ========================================================================= */
1437 void InitJoysticks()
1441 #if defined(NO_JOYSTICK)
1442 return; /* joysticks generally deactivated by compile-time directive */
1445 /* always start with reliable default values */
1446 joystick.status = JOYSTICK_NOT_AVAILABLE;
1447 for (i = 0; i < MAX_PLAYERS; i++)
1448 joystick.fd[i] = -1; /* joystick device closed */
1450 #if defined(TARGET_SDL)
1452 #elif defined(PLATFORM_UNIX)
1453 UnixInitJoysticks();
1454 #elif defined(PLATFORM_MSDOS)
1455 MSDOSInitJoysticks();
1459 for (i = 0; i < MAX_PLAYERS; i++)
1460 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1464 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1466 #if defined(TARGET_SDL)
1467 return SDLReadJoystick(nr, x, y, b1, b2);
1468 #elif defined(PLATFORM_UNIX)
1469 return UnixReadJoystick(nr, x, y, b1, b2);
1470 #elif defined(PLATFORM_MSDOS)
1471 return MSDOSReadJoystick(nr, x, y, b1, b2);