1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
32 struct PictureFileInfo
34 char *picture_filename;
35 boolean picture_with_mask;
40 char *picture_filename;
41 char *picturemask_filename;
44 #ifndef USE_SDL_LIBRARY
45 static int sound_process_id = 0;
48 static void InitPlayerInfo(void);
49 static void InitLevelInfo(void);
50 static void InitNetworkServer(void);
51 static void InitDisplay(void);
52 static void InitSound(void);
53 static void InitSoundServer(void);
54 static void InitWindow(int, char **);
55 static void InitGfx(void);
56 static void InitGfxBackground(void);
57 static void LoadGfx(int, struct PictureFileInfo *);
58 static void InitGadgets(void);
59 static void InitElementProperties(void);
61 void OpenAll(int argc, char *argv[])
63 #if defined(MSDOS) || defined(WIN32)
67 if (options.serveronly)
70 Error(ERR_WARN, "networking not supported in Windows version");
72 NetworkServer(options.server_port, options.serveronly);
85 InitRND(NEW_RANDOMIZE);
87 signal(SIGINT, CloseAllAndExit);
88 signal(SIGTERM, CloseAllAndExit);
91 InitWindow(argc, argv);
93 #ifndef USE_SDL_LIBRARY
94 XMapWindow(display, window);
99 InitElementProperties(); /* initializes IS_CHAR() for el2gfx() */
102 InitGadgets(); /* needs to know number of level series */
110 void InitPlayerInfo()
114 /* choose default local player */
115 local_player = &stored_player[0];
117 for (i=0; i<MAX_PLAYERS; i++)
119 stored_player[i].joystick_fd = -1; /* joystick device closed */
120 stored_player[i].connected = FALSE;
123 local_player->connected = TRUE;
125 LoadSetup(); /* global setup info */
130 LoadLevelInfo(); /* global level info */
131 LoadLevelSetup_LastSeries(); /* last played series info */
132 LoadLevelSetup_SeriesInfo(); /* last played level info */
135 void InitNetworkServer()
137 #if !defined(MSDOS) && !defined(WIN32)
141 if (!options.network)
144 #if !defined(MSDOS) && !defined(WIN32)
145 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
147 if (!ConnectToServer(options.server_host, options.server_port))
148 Error(ERR_EXIT, "cannot connect to network game server");
150 SendToServer_PlayerName(setup.player_name);
151 SendToServer_ProtocolVersion();
154 SendToServer_NrWanted(nr_wanted);
162 if (sound_status == SOUND_OFF)
165 #ifdef USE_SDL_LIBRARY
166 /* initialize SDL audio */
168 if (SDL_Init(SDL_INIT_AUDIO) < 0)
170 Error(ERR_WARN, "SDL_Init() failed: %s", SDL_GetError());
171 sound_status = SOUND_OFF;
175 if (Mix_OpenAudio(22050, AUDIO_S16, 2, 512) < 0)
177 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
178 sound_status = SOUND_OFF;
182 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
183 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
185 sound_status = SOUND_AVAILABLE;
186 sound_loops_allowed = TRUE;
188 #else /* !USE_SDL_LIBRARY */
190 #if !defined(MSDOS) && !defined(WIN32)
191 if (access(sound_device_name, W_OK) != 0)
193 Error(ERR_WARN, "cannot access sound device - no sounds");
194 sound_status = SOUND_OFF;
198 if ((sound_device = OpenAudio(sound_device_name)) < 0)
200 Error(ERR_WARN, "cannot open sound device - no sounds");
201 sound_status = SOUND_OFF;
206 sound_status = SOUND_AVAILABLE;
209 sound_loops_allowed = TRUE;
212 setup.sound_loops_on = TRUE;
216 #else /* MSDOS || WIN32 */
217 sound_loops_allowed = TRUE;
220 setup.sound_loops_on = TRUE;
223 #endif /* MSDOS || WIN32 */
224 #endif /* !USE_SDL_LIBRARY */
226 for(i=0; i<NUM_SOUNDS; i++)
228 Sound[i].name = sound_name[i];
230 if (!LoadSound(&Sound[i]))
232 sound_status = SOUND_OFF;
233 sound_loops_allowed = FALSE;
239 sound_status = SOUND_OFF;
244 void InitSoundServer()
246 if (sound_status == SOUND_OFF)
249 #ifndef USE_SDL_LIBRARY
251 #if !defined(MSDOS) && !defined(WIN32)
253 if (pipe(sound_pipe)<0)
255 Error(ERR_WARN, "cannot create pipe - no sounds");
256 sound_status = SOUND_OFF;
260 if ((sound_process_id = fork()) < 0)
262 Error(ERR_WARN, "cannot create sound server process - no sounds");
263 sound_status = SOUND_OFF;
267 if (!sound_process_id) /* we are child */
274 else /* we are parent */
275 close(sound_pipe[0]); /* no reading from pipe needed */
277 #else /* MSDOS || WIN32 */
283 #endif /* !USE_SDL_LIBRARY */
288 #ifdef USE_SDL_JOYSTICK
289 static boolean sdl_joystick_subsystem_initialized = FALSE;
294 if (global_joystick_status == JOYSTICK_OFF)
297 joystick_status = JOYSTICK_OFF;
299 #ifdef USE_SDL_JOYSTICK
301 if (!sdl_joystick_subsystem_initialized)
303 sdl_joystick_subsystem_initialized = TRUE;
305 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
307 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
312 for (i=0; i<MAX_PLAYERS; i++)
314 char *device_name = setup.input[i].joy.device_name;
315 int joystick_nr = getJoystickNrFromDeviceName(device_name);
317 if (joystick_nr >= SDL_NumJoysticks())
320 /* misuse joystick file descriptor variable to store joystick number */
321 stored_player[i].joystick_fd = joystick_nr;
323 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
324 if (Check_SDL_JoystickOpened(joystick_nr))
325 Close_SDL_Joystick(joystick_nr);
327 if (!setup.input[i].use_joystick)
330 if (!Open_SDL_Joystick(joystick_nr))
332 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
336 joystick_status = JOYSTICK_AVAILABLE;
339 #else /* !USE_SDL_JOYSTICK */
342 for (i=0; i<MAX_PLAYERS; i++)
344 char *device_name = setup.input[i].joy.device_name;
346 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
347 if (stored_player[i].joystick_fd != -1)
349 close(stored_player[i].joystick_fd);
350 stored_player[i].joystick_fd = -1;
353 if (!setup.input[i].use_joystick)
356 if (access(device_name, R_OK) != 0)
358 Error(ERR_WARN, "cannot access joystick device '%s'", device_name);
362 if ((stored_player[i].joystick_fd = open(device_name, O_RDONLY)) < 0)
364 Error(ERR_WARN, "cannot open joystick device '%s'", device_name);
368 joystick_status = JOYSTICK_AVAILABLE;
373 /* try to access two joysticks; if that fails, try to access just one */
374 if (install_joystick(JOY_TYPE_2PADS) == 0 ||
375 install_joystick(JOY_TYPE_AUTODETECT) == 0)
376 joystick_status = JOYSTICK_AVAILABLE;
379 load_joystick_data(JOYSTICK_FILENAME);
382 for (i=0; i<MAX_PLAYERS; i++)
384 char *device_name = setup.input[i].joy.device_name;
385 int joystick_nr = getJoystickNrFromDeviceName(device_name);
387 if (joystick_nr >= num_joysticks)
390 /* misuse joystick file descriptor variable to store joystick number */
391 stored_player[i].joystick_fd = joystick_nr;
395 #endif /* !USE_SDL_LIBRARY */
400 #ifdef USE_SDL_LIBRARY
401 /* initialize SDL video */
402 if (SDL_Init(SDL_INIT_VIDEO) < 0)
403 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
405 /* automatically cleanup SDL stuff after exit() */
408 #else /* !USE_SDL_LIBRARY */
411 XVisualInfo vinfo_template, *vinfo;
416 /* connect to X server */
417 if (!(display = XOpenDisplay(options.display_name)))
418 Error(ERR_EXIT, "cannot connect to X server %s",
419 XDisplayName(options.display_name));
421 screen = DefaultScreen(display);
422 visual = DefaultVisual(display, screen);
423 depth = DefaultDepth(display, screen);
424 cmap = DefaultColormap(display, screen);
427 /* look for good enough visual */
428 vinfo_template.screen = screen;
429 vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
430 vinfo_template.depth = depth;
431 if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
432 VisualDepthMask, &vinfo_template, &num_visuals)))
434 visual = vinfo->visual;
435 XFree((void *)vinfo);
438 /* got appropriate visual? */
441 printf("Sorry, displays with less than 8 bits per pixel not supported.\n");
444 else if ((depth ==8 && visual->class != PseudoColor) ||
445 (depth > 8 && visual->class != TrueColor &&
446 visual->class != DirectColor))
448 printf("Sorry, cannot get appropriate visual.\n");
452 #endif /* !USE_SDL_LIBRARY */
455 void InitWindow(int argc, char *argv[])
457 #ifdef USE_SDL_LIBRARY
458 /* open SDL video output device (window or fullscreen mode) */
460 if ((backbuffer = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
463 Error(ERR_EXIT, "SDL_SetVideoMode() failed: %s", SDL_GetError());
466 Error(ERR_EXIT, "setting video mode failed");
469 /* set window and icon title */
470 SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
472 /* set event filter to filter out certain mouse motion events */
473 SDL_SetEventFilter(EventFilter);
475 #else /* !USE_SDL_LIBRARY */
477 unsigned int border_width = 4;
479 unsigned long gc_valuemask;
481 XTextProperty windowName, iconName;
482 Pixmap icon_pixmap, iconmask_pixmap;
483 unsigned int icon_width, icon_height;
484 int icon_hot_x, icon_hot_y;
485 char icon_filename[256];
486 XSizeHints size_hints;
488 XClassHint class_hints;
489 char *window_name = WINDOW_TITLE_STRING;
490 char *icon_name = WINDOW_TITLE_STRING;
491 long window_event_mask;
492 Atom proto_atom = None, delete_atom = None;
494 int screen_width, screen_height;
495 int win_xpos = WIN_XPOS, win_ypos = WIN_YPOS;
496 unsigned long pen_fg = WhitePixel(display,screen);
497 unsigned long pen_bg = BlackPixel(display,screen);
498 const int width = WIN_XSIZE, height = WIN_YSIZE;
501 static struct IconFileInfo icon_pic =
508 screen_width = XDisplayWidth(display, screen);
509 screen_height = XDisplayHeight(display, screen);
511 win_xpos = (screen_width - width) / 2;
512 win_ypos = (screen_height - height) / 2;
514 window = XCreateSimpleWindow(display, RootWindow(display, screen),
515 win_xpos, win_ypos, width, height, border_width,
519 proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
520 delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
521 if ((proto_atom != None) && (delete_atom != None))
522 XChangeProperty(display, window, proto_atom, XA_ATOM, 32,
523 PropModePrepend, (unsigned char *) &delete_atom, 1);
525 sprintf(icon_filename, "%s/%s/%s",
526 options.ro_base_directory, GRAPHICS_DIRECTORY,
527 icon_pic.picture_filename);
528 XReadBitmapFile(display,window,icon_filename,
529 &icon_width,&icon_height,
530 &icon_pixmap,&icon_hot_x,&icon_hot_y);
532 Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
534 sprintf(icon_filename, "%s/%s/%s",
535 options.ro_base_directory, GRAPHICS_DIRECTORY,
536 icon_pic.picturemask_filename);
537 XReadBitmapFile(display,window,icon_filename,
538 &icon_width,&icon_height,
539 &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
540 if (!iconmask_pixmap)
541 Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
543 size_hints.width = size_hints.min_width = size_hints.max_width = width;
544 size_hints.height = size_hints.min_height = size_hints.max_height = height;
545 size_hints.flags = PSize | PMinSize | PMaxSize;
547 if (win_xpos || win_ypos)
549 size_hints.x = win_xpos;
550 size_hints.y = win_ypos;
551 size_hints.flags |= PPosition;
554 if (!XStringListToTextProperty(&window_name, 1, &windowName))
555 Error(ERR_EXIT, "structure allocation for windowName failed");
557 if (!XStringListToTextProperty(&icon_name, 1, &iconName))
558 Error(ERR_EXIT, "structure allocation for iconName failed");
560 wm_hints.initial_state = NormalState;
561 wm_hints.input = True;
562 wm_hints.icon_pixmap = icon_pixmap;
563 wm_hints.icon_mask = iconmask_pixmap;
564 wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
566 class_hints.res_name = program_name;
567 class_hints.res_class = "Rocks'n'Diamonds";
569 XSetWMProperties(display, window, &windowName, &iconName,
570 argv, argc, &size_hints, &wm_hints,
573 XFree(windowName.value);
574 XFree(iconName.value);
576 /* Select event types wanted */
578 ExposureMask | StructureNotifyMask | FocusChangeMask |
579 ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
580 PointerMotionHintMask | KeyPressMask | KeyReleaseMask;
582 XSelectInput(display, window, window_event_mask);
585 /* create GC for drawing with window depth and background color (black) */
586 gc_values.graphics_exposures = False;
587 gc_values.foreground = pen_bg;
588 gc_values.background = pen_bg;
589 gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
590 gc = XCreateGC(display, window, gc_valuemask, &gc_values);
591 #endif /* !USE_SDL_LIBRARY */
598 #ifdef USE_SDL_LIBRARY
599 SDL_Surface *sdl_image_tmp;
602 XGCValues clip_gc_values;
603 unsigned long clip_gc_valuemask;
607 static struct PictureFileInfo pic[NUM_PICTURES] =
621 static struct PictureFileInfo pic[NUM_PICTURES] =
623 { "RocksScreen", TRUE },
624 { "RocksDoor", TRUE },
625 { "RocksHeroes", TRUE },
626 { "RocksToons", TRUE },
629 { "RocksMore", TRUE },
630 { "RocksFont", FALSE },
631 { "RocksFont2", FALSE },
632 { "RocksFont3", FALSE }
638 static struct PictureFileInfo test_pic1 =
643 static struct PictureFileInfo test_pic2 =
656 tile_needs_clipping[] =
658 { GFX_SPIELER1_UP, 4 },
659 { GFX_SPIELER1_DOWN, 4 },
660 { GFX_SPIELER1_LEFT, 4 },
661 { GFX_SPIELER1_RIGHT, 4 },
662 { GFX_SPIELER1_PUSH_LEFT, 4 },
663 { GFX_SPIELER1_PUSH_RIGHT, 4 },
664 { GFX_SPIELER2_UP, 4 },
665 { GFX_SPIELER2_DOWN, 4 },
666 { GFX_SPIELER2_LEFT, 4 },
667 { GFX_SPIELER2_RIGHT, 4 },
668 { GFX_SPIELER2_PUSH_LEFT, 4 },
669 { GFX_SPIELER2_PUSH_RIGHT, 4 },
670 { GFX_SPIELER3_UP, 4 },
671 { GFX_SPIELER3_DOWN, 4 },
672 { GFX_SPIELER3_LEFT, 4 },
673 { GFX_SPIELER3_RIGHT, 4 },
674 { GFX_SPIELER3_PUSH_LEFT, 4 },
675 { GFX_SPIELER3_PUSH_RIGHT, 4 },
676 { GFX_SPIELER4_UP, 4 },
677 { GFX_SPIELER4_DOWN, 4 },
678 { GFX_SPIELER4_LEFT, 4 },
679 { GFX_SPIELER4_RIGHT, 4 },
680 { GFX_SPIELER4_PUSH_LEFT, 4 },
681 { GFX_SPIELER4_PUSH_RIGHT, 4 },
682 { GFX_SP_MURPHY, 1 },
683 { GFX_MURPHY_GO_LEFT, 3 },
684 { GFX_MURPHY_GO_RIGHT, 3 },
685 { GFX_MURPHY_SNAP_UP, 1 },
686 { GFX_MURPHY_SNAP_DOWN, 1 },
687 { GFX_MURPHY_SNAP_RIGHT, 1 },
688 { GFX_MURPHY_SNAP_LEFT, 1 },
689 { GFX_MURPHY_PUSH_RIGHT, 1 },
690 { GFX_MURPHY_PUSH_LEFT, 1 },
691 { GFX_GEBLUBBER, 4 },
694 { GFX_EXPLOSION, 8 },
695 { GFX_SOKOBAN_OBJEKT, 1 },
696 { GFX_FUNKELN_BLAU, 3 },
697 { GFX_FUNKELN_WEISS, 3 },
698 { GFX2_SHIELD_PASSIVE, 3 },
699 { GFX2_SHIELD_ACTIVE, 3 },
703 /* create additional image buffers for double-buffering */
705 #ifdef USE_SDL_LIBRARY
707 /* create some native image surfaces for double-buffer purposes */
709 /* create double-buffer surface for background image */
710 if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
711 WIN_XSIZE, WIN_YSIZE,
712 WIN_SDL_DEPTH, 0, 0, 0, 0))
714 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
716 if ((pix[PIX_DB_BACK] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
717 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
719 SDL_FreeSurface(sdl_image_tmp);
721 /* create double-buffer surface for door image */
722 if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
723 3 * DXSIZE, DYSIZE + VYSIZE,
724 WIN_SDL_DEPTH, 0, 0, 0, 0))
726 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
728 if ((pix[PIX_DB_DOOR] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
729 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
731 SDL_FreeSurface(sdl_image_tmp);
733 /* create double-buffer surface for field image */
734 if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
736 WIN_SDL_DEPTH, 0, 0, 0, 0))
738 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
740 if ((pix[PIX_DB_FIELD] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
741 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
743 SDL_FreeSurface(sdl_image_tmp);
745 /* SDL cannot directly draw to the visible video framebuffer like X11,
746 but always uses a backbuffer, which is then blitted to the visible
747 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
748 visible video framebuffer with 'SDL_Flip', if the hardware supports
749 this). Therefore do not use an additional backbuffer for drawing, but
750 use a symbolic buffer (distinguishable from the SDL backbuffer) called
751 'window', which indicates that the SDL backbuffer should be updated to
752 the visible video framebuffer when attempting to blit to it.
754 For convenience, it seems to be a good idea to create this symbolic
755 buffer 'window' at the same size as the SDL backbuffer. Although it
756 should never be drawn to directly, it would do no harm nevertheless. */
758 window = pix[PIX_DB_BACK]; /* 'window' is only symbolic buffer */
759 pix[PIX_DB_BACK] = backbuffer; /* 'backbuffer' is SDL screen buffer */
761 #else /* !USE_SDL_LIBRARY */
763 pix[PIX_DB_BACK] = XCreatePixmap(display, window,
765 XDefaultDepth(display,screen));
766 pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
767 3*DXSIZE,DYSIZE+VYSIZE,
768 XDefaultDepth(display,screen));
769 pix[PIX_DB_FIELD] = XCreatePixmap(display, window,
771 XDefaultDepth(display,screen));
773 if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR] || !pix[PIX_DB_FIELD])
774 Error(ERR_EXIT, "cannot create additional pixmaps");
776 #endif /* !USE_SDL_LIBRARY */
779 debug_print_timestamp(0, NULL); /* initialize timestamp function */
784 printf("Test: Loading RocksFont2.pcx ...\n");
785 LoadGfx(PIX_SMALLFONT,&test_pic1);
786 printf("Test: Done.\n");
787 printf("Test: Loading mouse.pcx ...\n");
788 LoadGfx(PIX_SMALLFONT,&test_pic2);
789 printf("Test: Done.\n");
793 LoadGfx(PIX_SMALLFONT, &pic[PIX_SMALLFONT]);
794 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
795 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
797 DrawInitText(PROGRAM_DOS_PORT_STRING, 210, FC_BLUE);
800 DrawInitText("Loading graphics:",120,FC_GREEN);
802 for(i=0; i<NUM_PICTURES; i++)
803 if (i != PIX_SMALLFONT)
807 debug_print_timestamp(0, "SUMMARY LOADING ALL GRAPHICS:");
810 /* create additional image buffers for masking of graphics */
812 #ifdef USE_SDL_LIBRARY
814 /* initialize surface array to 'NULL' */
815 for(i=0; i<NUM_TILES; i++)
816 tile_masked[i] = NULL;
818 /* create only those masked surfaces we really need */
819 for(i=0; tile_needs_clipping[i].start>=0; i++)
821 for(j=0; j<tile_needs_clipping[i].count; j++)
823 int tile = tile_needs_clipping[i].start + j;
829 getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
830 src_bitmap = pix_masked[bitmap_nr];
832 /* create surface for masked tile graphic */
833 if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, TILEX, TILEY,
834 WIN_SDL_DEPTH, 0, 0, 0, 0))
836 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
838 /* create native transparent surface for current image */
839 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
840 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
841 if ((tile_masked[tile] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
842 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
844 SDL_FreeSurface(sdl_image_tmp);
846 BlitBitmap(src_bitmap, tile_masked[tile], src_x,src_y, TILEX,TILEY, 0,0);
850 #else /* !USE_SDL_LIBRARY */
852 /* create graphic context structures needed for clipping */
853 clip_gc_values.graphics_exposures = False;
854 clip_gc_valuemask = GCGraphicsExposures;
856 XCreateGC(display, clipmask[PIX_BACK], clip_gc_valuemask, &clip_gc_values);
858 clip_gc_values.graphics_exposures = False;
859 clip_gc_valuemask = GCGraphicsExposures;
861 XCreateGC(display, window, clip_gc_valuemask, &clip_gc_values);
863 for(i=0; i<NUM_BITMAPS; i++)
867 clip_gc_values.graphics_exposures = False;
868 clip_gc_values.clip_mask = clipmask[i];
869 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
870 clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
874 /* initialize pixmap array to Pixmap 'None' */
875 for(i=0; i<NUM_TILES; i++)
876 tile_clipmask[i] = None;
878 /* create only those clipping Pixmaps we really need */
879 for(i=0; tile_needs_clipping[i].start>=0; i++)
881 for(j=0; j<tile_needs_clipping[i].count; j++)
883 int tile = tile_needs_clipping[i].start + j;
889 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
890 src_pixmap = clipmask[pixmap_nr];
892 tile_clipmask[tile] = XCreatePixmap(display, window, TILEX,TILEY, 1);
894 XCopyArea(display,src_pixmap,tile_clipmask[tile],copy_clipmask_gc,
895 src_x,src_y, TILEX,TILEY, 0,0);
899 #endif /* !USE_SDL_LIBRARY */
902 void InitGfxBackground()
906 drawto = backbuffer = pix[PIX_DB_BACK];
907 fieldbuffer = pix[PIX_DB_FIELD];
908 SetDrawtoField(DRAW_BACKBUFFER);
910 BlitBitmap(pix[PIX_BACK], backbuffer, 0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
911 ClearRectangle(backbuffer, REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
912 ClearRectangle(pix[PIX_DB_DOOR], 0,0, 3*DXSIZE,DYSIZE+VYSIZE);
914 for(x=0; x<MAX_BUF_XSIZE; x++)
915 for(y=0; y<MAX_BUF_YSIZE; y++)
918 redraw_mask = REDRAW_ALL;
921 void LoadGfx(int pos, struct PictureFileInfo *pic)
923 char basefilename[256];
926 #ifdef USE_XPM_LIBRARY
927 int xpm_err, xbm_err;
928 unsigned int width,height;
931 char *picture_ext = ".xpm";
932 char *picturemask_ext = "Mask.xbm";
935 #ifdef USE_SDL_LIBRARY
936 SDL_Surface *sdl_image_tmp;
937 #else /* !USE_SDL_LIBRARY */
939 #endif /* !USE_SDL_LIBRARY */
940 char *picture_ext = ".pcx";
942 #endif /* !USE_XPM_LIBRARY */
945 if (pic->picture_filename)
947 sprintf(basefilename, "%s%s", pic->picture_filename, picture_ext);
948 DrawInitText(basefilename, 150, FC_YELLOW);
949 sprintf(filename, "%s/%s/%s",
950 options.ro_base_directory, GRAPHICS_DIRECTORY, basefilename);
957 debug_print_timestamp(1, NULL); /* initialize timestamp function */
960 #ifdef USE_SDL_LIBRARY
961 /* load image to temporary surface */
962 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
963 Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
965 /* create native non-transparent surface for current image */
966 if ((pix[pos] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
967 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
969 /* create native transparent surface for current image */
970 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
971 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
972 if ((pix_masked[pos] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
973 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
975 /* free temporary surface */
976 SDL_FreeSurface(sdl_image_tmp);
978 #else /* !USE_SDL_LIBRARY */
980 #ifdef USE_XPM_LIBRARY
982 xpm_att[pos].valuemask = XpmCloseness;
983 xpm_att[pos].closeness = 20000;
984 xpm_err = XpmReadFileToPixmap(display,window,filename,
985 &pix[pos],&shapemask,&xpm_att[pos]);
989 Error(ERR_EXIT, "cannot open XPM file '%s'", filename);
991 Error(ERR_EXIT, "invalid XPM file '%s'", filename);
993 Error(ERR_EXIT, "not enough memory for XPM file '%s'", filename);
995 Error(ERR_EXIT, "cannot get colors for XPM file '%s'", filename);
1001 printf("LOADING XPM FILE %s:", filename);
1002 debug_print_timestamp(1, "");
1005 #else /* !USE_XPM_LIBRARY */
1007 pcx_err = Read_PCX_to_Pixmap(display, window, gc, filename,
1008 &pix[pos], &clipmask[pos]);
1013 case PCX_OpenFailed:
1014 Error(ERR_EXIT, "cannot open PCX file '%s'", filename);
1015 case PCX_ReadFailed:
1016 Error(ERR_EXIT, "cannot read PCX file '%s'", filename);
1017 case PCX_FileInvalid:
1018 Error(ERR_EXIT, "invalid PCX file '%s'", filename);
1020 Error(ERR_EXIT, "not enough memory for PCX file '%s'", filename);
1021 case PCX_ColorFailed:
1022 Error(ERR_EXIT, "cannot get colors for PCX file '%s'", filename);
1028 printf("SUMMARY LOADING PCX FILE %s:", filename);
1029 debug_print_timestamp(1, "");
1032 #endif /* !USE_XPM_LIBRARY */
1035 Error(ERR_EXIT, "cannot get graphics for '%s'", pic->picture_filename);
1037 /* setting pix_masked[] to pix[] allows BlitBitmapMasked() to always
1038 use pix_masked[], although they are the same when not using SDL */
1039 pix_masked[pos] = pix[pos];
1041 #endif /* !USE_SDL_LIBRARY */
1044 #ifndef USE_SDL_LIBRARY
1045 /* zugehörige Maske laden (wenn vorhanden) */
1046 if (pic->picture_with_mask)
1048 #ifdef USE_XPM_LIBRARY
1050 sprintf(basefilename, "%s%s", pic->picture_filename, picturemask_ext);
1051 DrawInitText(basefilename, 150, FC_YELLOW);
1052 sprintf(filename, "%s/%s/%s",
1053 options.ro_base_directory, GRAPHICS_DIRECTORY, basefilename);
1056 debug_print_timestamp(1, NULL); /* initialize timestamp function */
1059 xbm_err = XReadBitmapFile(display,window,filename,
1060 &width,&height,&clipmask[pos],&hot_x,&hot_y);
1065 case BitmapOpenFailed:
1066 Error(ERR_EXIT, "cannot open XBM file '%s'", filename);
1067 case BitmapFileInvalid:
1068 Error(ERR_EXIT, "invalid XBM file '%s'", filename);
1069 case BitmapNoMemory:
1070 Error(ERR_EXIT, "not enough memory for XBM file '%s'", filename);
1077 printf("LOADING XBM FILE %s:", filename);
1078 debug_print_timestamp(1, "");
1081 #endif /* USE_XPM_LIBRARY */
1084 Error(ERR_EXIT, "cannot get clipmask for '%s'", pic->picture_filename);
1086 #endif /* !USE_SDL_LIBRARY */
1091 CreateLevelEditorGadgets();
1092 CreateGameButtons();
1093 CreateTapeButtons();
1094 CreateToolButtons();
1095 CreateScreenGadgets();
1098 void InitElementProperties()
1102 static int ep_amoebalive[] =
1109 static int ep_amoebalive_num = sizeof(ep_amoebalive)/sizeof(int);
1111 static int ep_amoeboid[] =
1119 static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int);
1121 static int ep_schluessel[] =
1132 static int ep_schluessel_num = sizeof(ep_schluessel)/sizeof(int);
1134 static int ep_pforte[] =
1153 EL_SWITCHGATE_CLOSED,
1168 static int ep_pforte_num = sizeof(ep_pforte)/sizeof(int);
1170 static int ep_solid[] =
1191 EL_MAGIC_WALL_EMPTY,
1194 EL_MAGIC_WALL_BD_OFF,
1195 EL_MAGIC_WALL_BD_EMPTY,
1196 EL_MAGIC_WALL_BD_FULL,
1197 EL_MAGIC_WALL_BD_DEAD,
1224 EL_BELT1_SWITCH_LEFT,
1225 EL_BELT1_SWITCH_MIDDLE,
1226 EL_BELT1_SWITCH_RIGHT,
1227 EL_BELT2_SWITCH_LEFT,
1228 EL_BELT2_SWITCH_MIDDLE,
1229 EL_BELT2_SWITCH_RIGHT,
1230 EL_BELT3_SWITCH_LEFT,
1231 EL_BELT3_SWITCH_MIDDLE,
1232 EL_BELT3_SWITCH_RIGHT,
1233 EL_BELT4_SWITCH_LEFT,
1234 EL_BELT4_SWITCH_MIDDLE,
1235 EL_BELT4_SWITCH_RIGHT,
1236 EL_SWITCHGATE_SWITCH_1,
1237 EL_SWITCHGATE_SWITCH_2,
1238 EL_LIGHT_SWITCH_OFF,
1240 EL_TIMEGATE_SWITCH_OFF,
1241 EL_TIMEGATE_SWITCH_ON,
1242 EL_SIGN_EXCLAMATION,
1243 EL_SIGN_RADIOACTIVITY,
1255 EL_EMC_STEEL_WALL_1,
1256 EL_EMC_STEEL_WALL_2,
1257 EL_EMC_STEEL_WALL_3,
1258 EL_EMC_STEEL_WALL_4,
1282 static int ep_solid_num = sizeof(ep_solid)/sizeof(int);
1284 static int ep_massive[] =
1310 EL_SWITCHGATE_CLOSED,
1325 EL_BELT1_SWITCH_LEFT,
1326 EL_BELT1_SWITCH_MIDDLE,
1327 EL_BELT1_SWITCH_RIGHT,
1328 EL_BELT2_SWITCH_LEFT,
1329 EL_BELT2_SWITCH_MIDDLE,
1330 EL_BELT2_SWITCH_RIGHT,
1331 EL_BELT3_SWITCH_LEFT,
1332 EL_BELT3_SWITCH_MIDDLE,
1333 EL_BELT3_SWITCH_RIGHT,
1334 EL_BELT4_SWITCH_LEFT,
1335 EL_BELT4_SWITCH_MIDDLE,
1336 EL_BELT4_SWITCH_RIGHT,
1337 EL_LIGHT_SWITCH_OFF,
1339 EL_SIGN_EXCLAMATION,
1340 EL_SIGN_RADIOACTIVITY,
1352 EL_EMC_STEEL_WALL_1,
1353 EL_EMC_STEEL_WALL_2,
1354 EL_EMC_STEEL_WALL_3,
1355 EL_EMC_STEEL_WALL_4,
1369 static int ep_massive_num = sizeof(ep_massive)/sizeof(int);
1371 static int ep_slippery[] =
1406 static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
1408 static int ep_enemy[] =
1421 static int ep_enemy_num = sizeof(ep_enemy)/sizeof(int);
1423 static int ep_mauer[] =
1473 EL_EMC_STEEL_WALL_1,
1474 EL_EMC_STEEL_WALL_2,
1475 EL_EMC_STEEL_WALL_3,
1476 EL_EMC_STEEL_WALL_4,
1486 static int ep_mauer_num = sizeof(ep_mauer)/sizeof(int);
1488 static int ep_can_fall[] =
1503 EL_MAGIC_WALL_BD_FULL,
1514 static int ep_can_fall_num = sizeof(ep_can_fall)/sizeof(int);
1516 static int ep_can_smash[] =
1547 static int ep_can_smash_num = sizeof(ep_can_smash)/sizeof(int);
1549 static int ep_can_change[] =
1560 static int ep_can_change_num = sizeof(ep_can_change)/sizeof(int);
1562 static int ep_can_move[] =
1582 static int ep_can_move_num = sizeof(ep_can_move)/sizeof(int);
1584 static int ep_could_move[] =
1607 static int ep_could_move_num = sizeof(ep_could_move)/sizeof(int);
1609 static int ep_dont_touch[] =
1616 static int ep_dont_touch_num = sizeof(ep_dont_touch)/sizeof(int);
1618 static int ep_dont_go_to[] =
1636 static int ep_dont_go_to_num = sizeof(ep_dont_go_to)/sizeof(int);
1638 static int ep_mampf2[] =
1663 static int ep_mampf2_num = sizeof(ep_mampf2)/sizeof(int);
1665 static int ep_bd_element[] =
1674 EL_MAGIC_WALL_BD_OFF,
1692 static int ep_bd_element_num = sizeof(ep_bd_element)/sizeof(int);
1694 static int ep_sb_element[] =
1699 EL_SOKOBAN_FELD_LEER,
1700 EL_SOKOBAN_FELD_VOLL,
1704 static int ep_sb_element_num = sizeof(ep_sb_element)/sizeof(int);
1706 static int ep_gem[] =
1716 static int ep_gem_num = sizeof(ep_gem)/sizeof(int);
1718 static int ep_inactive[] =
1755 EL_DYNAMITE_INACTIVE,
1767 EL_SOKOBAN_FELD_LEER,
1768 EL_SOKOBAN_FELD_VOLL,
1778 EL_MAGIC_WALL_BD_OFF,
1779 EL_MAGIC_WALL_BD_DEAD,
1815 EL_BELT1_SWITCH_LEFT,
1816 EL_BELT1_SWITCH_MIDDLE,
1817 EL_BELT1_SWITCH_RIGHT,
1818 EL_BELT2_SWITCH_LEFT,
1819 EL_BELT2_SWITCH_MIDDLE,
1820 EL_BELT2_SWITCH_RIGHT,
1821 EL_BELT3_SWITCH_LEFT,
1822 EL_BELT3_SWITCH_MIDDLE,
1823 EL_BELT3_SWITCH_RIGHT,
1824 EL_BELT4_SWITCH_LEFT,
1825 EL_BELT4_SWITCH_MIDDLE,
1826 EL_BELT4_SWITCH_RIGHT,
1827 EL_SIGN_EXCLAMATION,
1828 EL_SIGN_RADIOACTIVITY,
1840 EL_EMC_STEEL_WALL_1,
1841 EL_EMC_STEEL_WALL_2,
1842 EL_EMC_STEEL_WALL_3,
1843 EL_EMC_STEEL_WALL_4,
1853 static int ep_inactive_num = sizeof(ep_inactive)/sizeof(int);
1855 static int ep_explosive[] =
1859 EL_DYNAMITE_INACTIVE,
1860 EL_DYNABOMB_ACTIVE_1,
1861 EL_DYNABOMB_ACTIVE_2,
1862 EL_DYNABOMB_ACTIVE_3,
1863 EL_DYNABOMB_ACTIVE_4,
1880 static int ep_explosive_num = sizeof(ep_explosive)/sizeof(int);
1882 static int ep_mampf3[] =
1893 static int ep_mampf3_num = sizeof(ep_mampf3)/sizeof(int);
1895 static int ep_pushable[] =
1902 EL_SOKOBAN_FELD_VOLL,
1912 static int ep_pushable_num = sizeof(ep_pushable)/sizeof(int);
1914 static int ep_player[] =
1922 static int ep_player_num = sizeof(ep_player)/sizeof(int);
1924 static int ep_has_content[] =
1932 static int ep_has_content_num = sizeof(ep_has_content)/sizeof(int);
1934 static int ep_eatable[] =
1942 static int ep_eatable_num = sizeof(ep_eatable)/sizeof(int);
1944 static int ep_sp_element[] =
1986 /* additional elements that appeared in newer Supaplex levels */
1988 /* more than one murphy in a level results in an inactive clone */
1991 static int ep_sp_element_num = sizeof(ep_sp_element)/sizeof(int);
1993 static int ep_quick_gate[] =
2017 static int ep_quick_gate_num = sizeof(ep_quick_gate)/sizeof(int);
2019 static int ep_over_player[] =
2044 static int ep_over_player_num = sizeof(ep_over_player)/sizeof(int);
2046 static int ep_active_bomb[] =
2049 EL_DYNABOMB_ACTIVE_1,
2050 EL_DYNABOMB_ACTIVE_2,
2051 EL_DYNABOMB_ACTIVE_3,
2052 EL_DYNABOMB_ACTIVE_4
2054 static int ep_active_bomb_num = sizeof(ep_active_bomb)/sizeof(int);
2056 static int ep_belt[] =
2071 static int ep_belt_num = sizeof(ep_belt)/sizeof(int);
2073 static int ep_belt_switch[] =
2075 EL_BELT1_SWITCH_LEFT,
2076 EL_BELT1_SWITCH_MIDDLE,
2077 EL_BELT1_SWITCH_RIGHT,
2078 EL_BELT2_SWITCH_LEFT,
2079 EL_BELT2_SWITCH_MIDDLE,
2080 EL_BELT2_SWITCH_RIGHT,
2081 EL_BELT3_SWITCH_LEFT,
2082 EL_BELT3_SWITCH_MIDDLE,
2083 EL_BELT3_SWITCH_RIGHT,
2084 EL_BELT4_SWITCH_LEFT,
2085 EL_BELT4_SWITCH_MIDDLE,
2086 EL_BELT4_SWITCH_RIGHT,
2088 static int ep_belt_switch_num = sizeof(ep_belt_switch)/sizeof(int);
2090 static int ep_tube[] =
2104 static int ep_tube_num = sizeof(ep_tube)/sizeof(int);
2106 static long ep1_bit[] =
2140 static long ep2_bit[] =
2146 static int *ep1_array[] =
2180 static int *ep2_array[] =
2186 static int *ep1_num[] =
2213 &ep_has_content_num,
2217 &ep_over_player_num,
2220 static int *ep2_num[] =
2223 &ep_belt_switch_num,
2226 static int num_properties1 = sizeof(ep1_num)/sizeof(int *);
2227 static int num_properties2 = sizeof(ep2_num)/sizeof(int *);
2229 for(i=0; i<MAX_ELEMENTS; i++)
2231 Elementeigenschaften1[i] = 0;
2232 Elementeigenschaften2[i] = 0;
2235 for(i=0; i<num_properties1; i++)
2236 for(j=0; j<*(ep1_num[i]); j++)
2237 Elementeigenschaften1[(ep1_array[i])[j]] |= ep1_bit[i];
2238 for(i=0; i<num_properties2; i++)
2239 for(j=0; j<*(ep2_num[i]); j++)
2240 Elementeigenschaften2[(ep2_array[i])[j]] |= ep2_bit[i];
2242 for(i=EL_CHAR_START; i<=EL_CHAR_END; i++)
2243 Elementeigenschaften1[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
2246 void CloseAllAndExit(int exit_value)
2250 #ifdef USE_SDL_LIBRARY
2252 FreeSounds(NUM_SOUNDS);
2254 if (sound_process_id)
2257 kill(sound_process_id, SIGTERM);
2258 FreeSounds(NUM_SOUNDS);
2262 for(i=0; i<NUM_BITMAPS; i++)
2266 #ifdef USE_XPM_LIBRARY
2267 if (i < NUM_PICTURES) /* XPM pictures */
2269 XFreeColors(display,DefaultColormap(display,screen),
2270 xpm_att[i].pixels,xpm_att[i].npixels,0);
2271 XpmFreeAttributes(&xpm_att[i]);
2275 #ifdef USE_SDL_LIBRARY
2276 SDL_FreeSurface(pix[i]);
2278 XFreePixmap(display,pix[i]);
2282 #ifdef USE_SDL_LIBRARY
2283 SDL_FreeSurface(pix_masked[i]);
2286 XFreePixmap(display,clipmask[i]);
2288 XFreeGC(display, clip_gc[i]);
2292 #ifdef USE_SDL_LIBRARY
2293 KeyboardAutoRepeatOn();
2296 XFreeGC(display, gc);
2300 KeyboardAutoRepeatOn();
2301 XCloseDisplay(display);
2305 #if defined(MSDOS) || defined(WIN32)