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;
41 char *picture_filename;
42 char *picturemask_filename;
46 #ifndef USE_SDL_LIBRARY
47 static int sound_process_id = 0;
50 static void InitPlayerInfo(void);
51 static void InitLevelInfo(void);
52 static void InitNetworkServer(void);
54 static void InitDisplay(void);
56 static void InitSound(void);
57 static void InitSoundServer(void);
59 static void InitWindow(int, char **);
61 static void InitGfx(void);
62 static void InitGfxBackground(void);
63 static void LoadGfx(int, struct PictureFileInfo *);
64 static void InitGadgets(void);
65 static void InitElementProperties(void);
67 void OpenAll(int argc, char *argv[])
69 #if defined(MSDOS) || defined(WIN32)
73 if (options.serveronly)
76 Error(ERR_WARN, "networking not supported in Windows version");
78 NetworkServer(options.server_port, options.serveronly);
91 InitRND(NEW_RANDOMIZE);
93 signal(SIGINT, CloseAllAndExit);
94 signal(SIGTERM, CloseAllAndExit);
97 InitBufferedDisplay(&backbuffer, &window);
98 InitEventFilter(FilterMouseMotionEvents);
105 InitWindow(argc, argv);
108 #ifndef USE_SDL_LIBRARY
109 XMapWindow(display, window);
119 InitElementProperties(); /* initializes IS_CHAR() for el2gfx() */
122 InitGadgets(); /* needs to know number of level series */
130 void InitPlayerInfo()
134 /* choose default local player */
135 local_player = &stored_player[0];
137 for (i=0; i<MAX_PLAYERS; i++)
139 stored_player[i].joystick_fd = -1; /* joystick device closed */
140 stored_player[i].connected = FALSE;
143 local_player->connected = TRUE;
145 LoadSetup(); /* global setup info */
150 LoadLevelInfo(); /* global level info */
151 LoadLevelSetup_LastSeries(); /* last played series info */
152 LoadLevelSetup_SeriesInfo(); /* last played level info */
155 void InitNetworkServer()
157 #if !defined(MSDOS) && !defined(WIN32)
161 if (!options.network)
164 #if !defined(MSDOS) && !defined(WIN32)
165 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
167 if (!ConnectToServer(options.server_host, options.server_port))
168 Error(ERR_EXIT, "cannot connect to network game server");
170 SendToServer_PlayerName(setup.player_name);
171 SendToServer_ProtocolVersion();
174 SendToServer_NrWanted(nr_wanted);
182 if (sound_status == SOUND_OFF)
185 #ifdef USE_SDL_LIBRARY
186 /* initialize SDL audio */
188 if (SDL_Init(SDL_INIT_AUDIO) < 0)
190 Error(ERR_WARN, "SDL_Init() failed: %s", SDL_GetError());
191 sound_status = SOUND_OFF;
195 if (Mix_OpenAudio(22050, AUDIO_S16, 2, 512) < 0)
197 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
198 sound_status = SOUND_OFF;
202 Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4);
203 Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4);
205 sound_status = SOUND_AVAILABLE;
206 sound_loops_allowed = TRUE;
208 #else /* !USE_SDL_LIBRARY */
210 #if !defined(MSDOS) && !defined(WIN32)
211 if (access(sound_device_name, W_OK) != 0)
213 Error(ERR_WARN, "cannot access sound device - no sounds");
214 sound_status = SOUND_OFF;
218 if ((sound_device = OpenAudio(sound_device_name)) < 0)
220 Error(ERR_WARN, "cannot open sound device - no sounds");
221 sound_status = SOUND_OFF;
226 sound_status = SOUND_AVAILABLE;
229 sound_loops_allowed = TRUE;
232 setup.sound_loops_on = TRUE;
236 #else /* MSDOS || WIN32 */
237 sound_loops_allowed = TRUE;
240 setup.sound_loops_on = TRUE;
243 #endif /* MSDOS || WIN32 */
244 #endif /* !USE_SDL_LIBRARY */
246 for(i=0; i<NUM_SOUNDS; i++)
248 Sound[i].name = sound_name[i];
250 if (!LoadSound(&Sound[i]))
252 sound_status = SOUND_OFF;
253 sound_loops_allowed = FALSE;
259 sound_status = SOUND_OFF;
264 void InitSoundServer()
266 if (sound_status == SOUND_OFF)
269 #ifndef USE_SDL_LIBRARY
271 #if !defined(MSDOS) && !defined(WIN32)
273 if (pipe(sound_pipe)<0)
275 Error(ERR_WARN, "cannot create pipe - no sounds");
276 sound_status = SOUND_OFF;
280 if ((sound_process_id = fork()) < 0)
282 Error(ERR_WARN, "cannot create sound server process - no sounds");
283 sound_status = SOUND_OFF;
287 if (!sound_process_id) /* we are child */
294 else /* we are parent */
295 close(sound_pipe[0]); /* no reading from pipe needed */
297 #else /* MSDOS || WIN32 */
303 #endif /* !USE_SDL_LIBRARY */
308 #ifdef USE_SDL_JOYSTICK
309 static boolean sdl_joystick_subsystem_initialized = FALSE;
314 if (global_joystick_status == JOYSTICK_OFF)
317 joystick_status = JOYSTICK_OFF;
319 #ifdef USE_SDL_JOYSTICK
321 if (!sdl_joystick_subsystem_initialized)
323 sdl_joystick_subsystem_initialized = TRUE;
325 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
327 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
332 for (i=0; i<MAX_PLAYERS; i++)
334 char *device_name = setup.input[i].joy.device_name;
335 int joystick_nr = getJoystickNrFromDeviceName(device_name);
337 if (joystick_nr >= SDL_NumJoysticks())
340 /* misuse joystick file descriptor variable to store joystick number */
341 stored_player[i].joystick_fd = joystick_nr;
343 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
344 if (Check_SDL_JoystickOpened(joystick_nr))
345 Close_SDL_Joystick(joystick_nr);
347 if (!setup.input[i].use_joystick)
350 if (!Open_SDL_Joystick(joystick_nr))
352 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
356 joystick_status = JOYSTICK_AVAILABLE;
359 #else /* !USE_SDL_JOYSTICK */
362 for (i=0; i<MAX_PLAYERS; i++)
364 char *device_name = setup.input[i].joy.device_name;
366 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
367 if (stored_player[i].joystick_fd != -1)
369 close(stored_player[i].joystick_fd);
370 stored_player[i].joystick_fd = -1;
373 if (!setup.input[i].use_joystick)
376 if (access(device_name, R_OK) != 0)
378 Error(ERR_WARN, "cannot access joystick device '%s'", device_name);
382 if ((stored_player[i].joystick_fd = open(device_name, O_RDONLY)) < 0)
384 Error(ERR_WARN, "cannot open joystick device '%s'", device_name);
388 joystick_status = JOYSTICK_AVAILABLE;
393 /* try to access two joysticks; if that fails, try to access just one */
394 if (install_joystick(JOY_TYPE_2PADS) == 0 ||
395 install_joystick(JOY_TYPE_AUTODETECT) == 0)
396 joystick_status = JOYSTICK_AVAILABLE;
399 load_joystick_data(JOYSTICK_FILENAME);
402 for (i=0; i<MAX_PLAYERS; i++)
404 char *device_name = setup.input[i].joy.device_name;
405 int joystick_nr = getJoystickNrFromDeviceName(device_name);
407 if (joystick_nr >= num_joysticks)
410 /* misuse joystick file descriptor variable to store joystick number */
411 stored_player[i].joystick_fd = joystick_nr;
415 #endif /* !USE_SDL_LIBRARY */
424 #ifdef USE_SDL_LIBRARY
425 /* initialize SDL video */
426 if (SDL_Init(SDL_INIT_VIDEO) < 0)
427 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
429 /* automatically cleanup SDL stuff after exit() */
432 #else /* !USE_SDL_LIBRARY */
435 XVisualInfo vinfo_template, *vinfo;
440 /* connect to X server */
441 if (!(display = XOpenDisplay(options.display_name)))
442 Error(ERR_EXIT, "cannot connect to X server %s",
443 XDisplayName(options.display_name));
445 screen = DefaultScreen(display);
446 visual = DefaultVisual(display, screen);
447 depth = DefaultDepth(display, screen);
448 cmap = DefaultColormap(display, screen);
451 /* look for good enough visual */
452 vinfo_template.screen = screen;
453 vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
454 vinfo_template.depth = depth;
455 if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
456 VisualDepthMask, &vinfo_template, &num_visuals)))
458 visual = vinfo->visual;
459 XFree((void *)vinfo);
462 /* got appropriate visual? */
465 printf("Sorry, displays with less than 8 bits per pixel not supported.\n");
468 else if ((depth ==8 && visual->class != PseudoColor) ||
469 (depth > 8 && visual->class != TrueColor &&
470 visual->class != DirectColor))
472 printf("Sorry, cannot get appropriate visual.\n");
476 #endif /* !USE_SDL_LIBRARY */
479 void InitWindow(int argc, char *argv[])
481 #ifdef USE_SDL_LIBRARY
482 /* open SDL video output device (window or fullscreen mode) */
484 if ((backbuffer = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
487 Error(ERR_EXIT, "SDL_SetVideoMode() failed: %s", SDL_GetError());
490 Error(ERR_EXIT, "setting video mode failed");
493 /* set window and icon title */
494 SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
496 /* set event filter to filter out certain mouse motion events */
497 SDL_SetEventFilter(EventFilter);
499 #else /* !USE_SDL_LIBRARY */
501 unsigned int border_width = 4;
503 unsigned long gc_valuemask;
505 XTextProperty windowName, iconName;
506 Pixmap icon_pixmap, iconmask_pixmap;
507 unsigned int icon_width, icon_height;
508 int icon_hot_x, icon_hot_y;
509 char icon_filename[256];
510 XSizeHints size_hints;
512 XClassHint class_hints;
513 char *window_name = WINDOW_TITLE_STRING;
514 char *icon_name = WINDOW_TITLE_STRING;
515 long window_event_mask;
516 Atom proto_atom = None, delete_atom = None;
518 int screen_width, screen_height;
519 int win_xpos = WIN_XPOS, win_ypos = WIN_YPOS;
520 unsigned long pen_fg = WhitePixel(display,screen);
521 unsigned long pen_bg = BlackPixel(display,screen);
522 const int width = WIN_XSIZE, height = WIN_YSIZE;
525 static struct IconFileInfo icon_pic =
532 screen_width = XDisplayWidth(display, screen);
533 screen_height = XDisplayHeight(display, screen);
535 win_xpos = (screen_width - width) / 2;
536 win_ypos = (screen_height - height) / 2;
538 window = XCreateSimpleWindow(display, RootWindow(display, screen),
539 win_xpos, win_ypos, width, height, border_width,
543 proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
544 delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
545 if ((proto_atom != None) && (delete_atom != None))
546 XChangeProperty(display, window, proto_atom, XA_ATOM, 32,
547 PropModePrepend, (unsigned char *) &delete_atom, 1);
549 sprintf(icon_filename, "%s/%s/%s",
550 options.ro_base_directory, GRAPHICS_DIRECTORY,
551 icon_pic.picture_filename);
552 XReadBitmapFile(display,window,icon_filename,
553 &icon_width,&icon_height,
554 &icon_pixmap,&icon_hot_x,&icon_hot_y);
556 Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
558 sprintf(icon_filename, "%s/%s/%s",
559 options.ro_base_directory, GRAPHICS_DIRECTORY,
560 icon_pic.picturemask_filename);
561 XReadBitmapFile(display,window,icon_filename,
562 &icon_width,&icon_height,
563 &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
564 if (!iconmask_pixmap)
565 Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
567 size_hints.width = size_hints.min_width = size_hints.max_width = width;
568 size_hints.height = size_hints.min_height = size_hints.max_height = height;
569 size_hints.flags = PSize | PMinSize | PMaxSize;
571 if (win_xpos || win_ypos)
573 size_hints.x = win_xpos;
574 size_hints.y = win_ypos;
575 size_hints.flags |= PPosition;
578 if (!XStringListToTextProperty(&window_name, 1, &windowName))
579 Error(ERR_EXIT, "structure allocation for windowName failed");
581 if (!XStringListToTextProperty(&icon_name, 1, &iconName))
582 Error(ERR_EXIT, "structure allocation for iconName failed");
584 wm_hints.initial_state = NormalState;
585 wm_hints.input = True;
586 wm_hints.icon_pixmap = icon_pixmap;
587 wm_hints.icon_mask = iconmask_pixmap;
588 wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
590 class_hints.res_name = program_name;
591 class_hints.res_class = "Rocks'n'Diamonds";
593 XSetWMProperties(display, window, &windowName, &iconName,
594 argv, argc, &size_hints, &wm_hints,
597 XFree(windowName.value);
598 XFree(iconName.value);
600 /* Select event types wanted */
602 ExposureMask | StructureNotifyMask | FocusChangeMask |
603 ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
604 PointerMotionHintMask | KeyPressMask | KeyReleaseMask;
606 XSelectInput(display, window, window_event_mask);
609 /* create GC for drawing with window depth and background color (black) */
610 gc_values.graphics_exposures = False;
611 gc_values.foreground = pen_bg;
612 gc_values.background = pen_bg;
613 gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
614 gc = XCreateGC(display, window, gc_valuemask, &gc_values);
615 #endif /* !USE_SDL_LIBRARY */
626 #ifdef USE_SDL_LIBRARY
627 SDL_Surface *sdl_image_tmp;
630 XGCValues clip_gc_values;
631 unsigned long clip_gc_valuemask;
635 static struct PictureFileInfo pic[NUM_PICTURES] =
649 static struct PictureFileInfo pic[NUM_PICTURES] =
651 { "RocksScreen", TRUE },
652 { "RocksDoor", TRUE },
653 { "RocksHeroes", TRUE },
654 { "RocksToons", TRUE },
657 { "RocksMore", TRUE },
658 { "RocksFont", FALSE },
659 { "RocksFont2", FALSE },
660 { "RocksFont3", FALSE }
666 static struct PictureFileInfo test_pic1 =
671 static struct PictureFileInfo test_pic2 =
684 tile_needs_clipping[] =
686 { GFX_SPIELER1_UP, 4 },
687 { GFX_SPIELER1_DOWN, 4 },
688 { GFX_SPIELER1_LEFT, 4 },
689 { GFX_SPIELER1_RIGHT, 4 },
690 { GFX_SPIELER1_PUSH_LEFT, 4 },
691 { GFX_SPIELER1_PUSH_RIGHT, 4 },
692 { GFX_SPIELER2_UP, 4 },
693 { GFX_SPIELER2_DOWN, 4 },
694 { GFX_SPIELER2_LEFT, 4 },
695 { GFX_SPIELER2_RIGHT, 4 },
696 { GFX_SPIELER2_PUSH_LEFT, 4 },
697 { GFX_SPIELER2_PUSH_RIGHT, 4 },
698 { GFX_SPIELER3_UP, 4 },
699 { GFX_SPIELER3_DOWN, 4 },
700 { GFX_SPIELER3_LEFT, 4 },
701 { GFX_SPIELER3_RIGHT, 4 },
702 { GFX_SPIELER3_PUSH_LEFT, 4 },
703 { GFX_SPIELER3_PUSH_RIGHT, 4 },
704 { GFX_SPIELER4_UP, 4 },
705 { GFX_SPIELER4_DOWN, 4 },
706 { GFX_SPIELER4_LEFT, 4 },
707 { GFX_SPIELER4_RIGHT, 4 },
708 { GFX_SPIELER4_PUSH_LEFT, 4 },
709 { GFX_SPIELER4_PUSH_RIGHT, 4 },
710 { GFX_SP_MURPHY, 1 },
711 { GFX_MURPHY_GO_LEFT, 3 },
712 { GFX_MURPHY_GO_RIGHT, 3 },
713 { GFX_MURPHY_SNAP_UP, 1 },
714 { GFX_MURPHY_SNAP_DOWN, 1 },
715 { GFX_MURPHY_SNAP_RIGHT, 1 },
716 { GFX_MURPHY_SNAP_LEFT, 1 },
717 { GFX_MURPHY_PUSH_RIGHT, 1 },
718 { GFX_MURPHY_PUSH_LEFT, 1 },
719 { GFX_GEBLUBBER, 4 },
722 { GFX_EXPLOSION, 8 },
723 { GFX_SOKOBAN_OBJEKT, 1 },
724 { GFX_FUNKELN_BLAU, 3 },
725 { GFX_FUNKELN_WEISS, 3 },
726 { GFX2_SHIELD_PASSIVE, 3 },
727 { GFX2_SHIELD_ACTIVE, 3 },
731 /* create additional image buffers for double-buffering */
734 pix[PIX_DB_BACK] = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
736 pix[PIX_DB_DOOR] = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
737 pix[PIX_DB_FIELD] = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
743 #ifdef USE_SDL_LIBRARY
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 #endif /* !USE_SDL_LIBRARY */
768 debug_print_timestamp(0, NULL); /* initialize timestamp function */
773 printf("Test: Loading RocksFont2.pcx ...\n");
774 LoadGfx(PIX_SMALLFONT,&test_pic1);
775 printf("Test: Done.\n");
776 printf("Test: Loading mouse.pcx ...\n");
777 LoadGfx(PIX_SMALLFONT,&test_pic2);
778 printf("Test: Done.\n");
782 LoadGfx(PIX_SMALLFONT, &pic[PIX_SMALLFONT]);
783 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
784 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
786 DrawInitText(PROGRAM_DOS_PORT_STRING, 210, FC_BLUE);
789 DrawInitText("Loading graphics:",120,FC_GREEN);
791 for(i=0; i<NUM_PICTURES; i++)
792 if (i != PIX_SMALLFONT)
796 debug_print_timestamp(0, "SUMMARY LOADING ALL GRAPHICS:");
799 /* create additional image buffers for masking of graphics */
801 #ifdef USE_SDL_LIBRARY
803 /* initialize surface array to 'NULL' */
804 for(i=0; i<NUM_TILES; i++)
805 tile_masked[i] = NULL;
807 /* create only those masked surfaces we really need */
808 for(i=0; tile_needs_clipping[i].start>=0; i++)
810 for(j=0; j<tile_needs_clipping[i].count; j++)
812 int tile = tile_needs_clipping[i].start + j;
818 getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
819 src_bitmap = pix_masked[bitmap_nr];
821 /* create surface for masked tile graphic */
822 if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, TILEX, TILEY,
823 WIN_SDL_DEPTH, 0, 0, 0, 0))
825 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
827 /* create native transparent surface for current image */
828 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
829 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
830 if ((tile_masked[tile] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
831 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
833 SDL_FreeSurface(sdl_image_tmp);
835 BlitBitmap(src_bitmap, tile_masked[tile], src_x,src_y, TILEX,TILEY, 0,0);
839 #else /* !USE_SDL_LIBRARY */
841 /* create graphic context structures needed for clipping */
842 clip_gc_values.graphics_exposures = False;
843 clip_gc_valuemask = GCGraphicsExposures;
845 XCreateGC(display, clipmask[PIX_BACK], clip_gc_valuemask, &clip_gc_values);
847 clip_gc_values.graphics_exposures = False;
848 clip_gc_valuemask = GCGraphicsExposures;
850 XCreateGC(display, window, clip_gc_valuemask, &clip_gc_values);
852 for(i=0; i<NUM_BITMAPS; i++)
856 clip_gc_values.graphics_exposures = False;
857 clip_gc_values.clip_mask = clipmask[i];
858 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
859 clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
863 /* initialize pixmap array to Pixmap 'None' */
864 for(i=0; i<NUM_TILES; i++)
865 tile_clipmask[i] = None;
867 /* create only those clipping Pixmaps we really need */
868 for(i=0; tile_needs_clipping[i].start>=0; i++)
870 for(j=0; j<tile_needs_clipping[i].count; j++)
872 int tile = tile_needs_clipping[i].start + j;
878 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
879 src_pixmap = clipmask[pixmap_nr];
881 tile_clipmask[tile] = XCreatePixmap(display, window, TILEX,TILEY, 1);
883 XCopyArea(display,src_pixmap,tile_clipmask[tile],copy_clipmask_gc,
884 src_x,src_y, TILEX,TILEY, 0,0);
888 #endif /* !USE_SDL_LIBRARY */
891 void InitGfxBackground()
895 drawto = backbuffer = pix[PIX_DB_BACK];
896 fieldbuffer = pix[PIX_DB_FIELD];
897 SetDrawtoField(DRAW_BACKBUFFER);
899 BlitBitmap(pix[PIX_BACK], backbuffer, 0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
900 ClearRectangle(backbuffer, REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
901 ClearRectangle(pix[PIX_DB_DOOR], 0,0, 3*DXSIZE,DYSIZE+VYSIZE);
903 for(x=0; x<MAX_BUF_XSIZE; x++)
904 for(y=0; y<MAX_BUF_YSIZE; y++)
907 redraw_mask = REDRAW_ALL;
910 void LoadGfx(int pos, struct PictureFileInfo *pic)
912 char basefilename[256];
915 #ifdef USE_XPM_LIBRARY
916 int xpm_err, xbm_err;
917 unsigned int width,height;
920 char *picture_ext = ".xpm";
921 char *picturemask_ext = "Mask.xbm";
924 #ifdef USE_SDL_LIBRARY
925 SDL_Surface *sdl_image_tmp;
926 #else /* !USE_SDL_LIBRARY */
928 #endif /* !USE_SDL_LIBRARY */
929 char *picture_ext = ".pcx";
931 #endif /* !USE_XPM_LIBRARY */
934 if (pic->picture_filename)
936 sprintf(basefilename, "%s%s", pic->picture_filename, picture_ext);
937 DrawInitText(basefilename, 150, FC_YELLOW);
938 sprintf(filename, "%s/%s/%s",
939 options.ro_base_directory, GRAPHICS_DIRECTORY, basefilename);
946 debug_print_timestamp(1, NULL); /* initialize timestamp function */
949 #ifdef USE_SDL_LIBRARY
950 /* load image to temporary surface */
951 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
952 Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
954 /* create native non-transparent surface for current image */
955 if ((pix[pos] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
956 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
958 /* create native transparent surface for current image */
959 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
960 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
961 if ((pix_masked[pos] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
962 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
964 /* free temporary surface */
965 SDL_FreeSurface(sdl_image_tmp);
967 #else /* !USE_SDL_LIBRARY */
969 #ifdef USE_XPM_LIBRARY
971 xpm_att[pos].valuemask = XpmCloseness;
972 xpm_att[pos].closeness = 20000;
973 xpm_err = XpmReadFileToPixmap(display,window,filename,
974 &pix[pos],&shapemask,&xpm_att[pos]);
978 Error(ERR_EXIT, "cannot open XPM file '%s'", filename);
980 Error(ERR_EXIT, "invalid XPM file '%s'", filename);
982 Error(ERR_EXIT, "not enough memory for XPM file '%s'", filename);
984 Error(ERR_EXIT, "cannot get colors for XPM file '%s'", filename);
990 printf("LOADING XPM FILE %s:", filename);
991 debug_print_timestamp(1, "");
994 #else /* !USE_XPM_LIBRARY */
996 pcx_err = Read_PCX_to_Pixmap(display, window, gc, filename,
997 &pix[pos], &clipmask[pos]);
1002 case PCX_OpenFailed:
1003 Error(ERR_EXIT, "cannot open PCX file '%s'", filename);
1004 case PCX_ReadFailed:
1005 Error(ERR_EXIT, "cannot read PCX file '%s'", filename);
1006 case PCX_FileInvalid:
1007 Error(ERR_EXIT, "invalid PCX file '%s'", filename);
1009 Error(ERR_EXIT, "not enough memory for PCX file '%s'", filename);
1010 case PCX_ColorFailed:
1011 Error(ERR_EXIT, "cannot get colors for PCX file '%s'", filename);
1017 printf("SUMMARY LOADING PCX FILE %s:", filename);
1018 debug_print_timestamp(1, "");
1021 #endif /* !USE_XPM_LIBRARY */
1024 Error(ERR_EXIT, "cannot get graphics for '%s'", pic->picture_filename);
1026 /* setting pix_masked[] to pix[] allows BlitBitmapMasked() to always
1027 use pix_masked[], although they are the same when not using SDL */
1028 pix_masked[pos] = pix[pos];
1030 #endif /* !USE_SDL_LIBRARY */
1033 #ifndef USE_SDL_LIBRARY
1034 /* zugehörige Maske laden (wenn vorhanden) */
1035 if (pic->picture_with_mask)
1037 #ifdef USE_XPM_LIBRARY
1039 sprintf(basefilename, "%s%s", pic->picture_filename, picturemask_ext);
1040 DrawInitText(basefilename, 150, FC_YELLOW);
1041 sprintf(filename, "%s/%s/%s",
1042 options.ro_base_directory, GRAPHICS_DIRECTORY, basefilename);
1045 debug_print_timestamp(1, NULL); /* initialize timestamp function */
1048 xbm_err = XReadBitmapFile(display,window,filename,
1049 &width,&height,&clipmask[pos],&hot_x,&hot_y);
1054 case BitmapOpenFailed:
1055 Error(ERR_EXIT, "cannot open XBM file '%s'", filename);
1056 case BitmapFileInvalid:
1057 Error(ERR_EXIT, "invalid XBM file '%s'", filename);
1058 case BitmapNoMemory:
1059 Error(ERR_EXIT, "not enough memory for XBM file '%s'", filename);
1066 printf("LOADING XBM FILE %s:", filename);
1067 debug_print_timestamp(1, "");
1070 #endif /* USE_XPM_LIBRARY */
1073 Error(ERR_EXIT, "cannot get clipmask for '%s'", pic->picture_filename);
1075 #endif /* !USE_SDL_LIBRARY */
1080 CreateLevelEditorGadgets();
1081 CreateGameButtons();
1082 CreateTapeButtons();
1083 CreateToolButtons();
1084 CreateScreenGadgets();
1087 void InitElementProperties()
1091 static int ep_amoebalive[] =
1098 static int ep_amoebalive_num = sizeof(ep_amoebalive)/sizeof(int);
1100 static int ep_amoeboid[] =
1108 static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int);
1110 static int ep_schluessel[] =
1121 static int ep_schluessel_num = sizeof(ep_schluessel)/sizeof(int);
1123 static int ep_pforte[] =
1142 EL_SWITCHGATE_CLOSED,
1157 static int ep_pforte_num = sizeof(ep_pforte)/sizeof(int);
1159 static int ep_solid[] =
1180 EL_MAGIC_WALL_EMPTY,
1183 EL_MAGIC_WALL_BD_OFF,
1184 EL_MAGIC_WALL_BD_EMPTY,
1185 EL_MAGIC_WALL_BD_FULL,
1186 EL_MAGIC_WALL_BD_DEAD,
1213 EL_BELT1_SWITCH_LEFT,
1214 EL_BELT1_SWITCH_MIDDLE,
1215 EL_BELT1_SWITCH_RIGHT,
1216 EL_BELT2_SWITCH_LEFT,
1217 EL_BELT2_SWITCH_MIDDLE,
1218 EL_BELT2_SWITCH_RIGHT,
1219 EL_BELT3_SWITCH_LEFT,
1220 EL_BELT3_SWITCH_MIDDLE,
1221 EL_BELT3_SWITCH_RIGHT,
1222 EL_BELT4_SWITCH_LEFT,
1223 EL_BELT4_SWITCH_MIDDLE,
1224 EL_BELT4_SWITCH_RIGHT,
1225 EL_SWITCHGATE_SWITCH_1,
1226 EL_SWITCHGATE_SWITCH_2,
1227 EL_LIGHT_SWITCH_OFF,
1229 EL_TIMEGATE_SWITCH_OFF,
1230 EL_TIMEGATE_SWITCH_ON,
1231 EL_SIGN_EXCLAMATION,
1232 EL_SIGN_RADIOACTIVITY,
1244 EL_EMC_STEEL_WALL_1,
1245 EL_EMC_STEEL_WALL_2,
1246 EL_EMC_STEEL_WALL_3,
1247 EL_EMC_STEEL_WALL_4,
1271 static int ep_solid_num = sizeof(ep_solid)/sizeof(int);
1273 static int ep_massive[] =
1299 EL_SWITCHGATE_CLOSED,
1314 EL_BELT1_SWITCH_LEFT,
1315 EL_BELT1_SWITCH_MIDDLE,
1316 EL_BELT1_SWITCH_RIGHT,
1317 EL_BELT2_SWITCH_LEFT,
1318 EL_BELT2_SWITCH_MIDDLE,
1319 EL_BELT2_SWITCH_RIGHT,
1320 EL_BELT3_SWITCH_LEFT,
1321 EL_BELT3_SWITCH_MIDDLE,
1322 EL_BELT3_SWITCH_RIGHT,
1323 EL_BELT4_SWITCH_LEFT,
1324 EL_BELT4_SWITCH_MIDDLE,
1325 EL_BELT4_SWITCH_RIGHT,
1326 EL_LIGHT_SWITCH_OFF,
1328 EL_SIGN_EXCLAMATION,
1329 EL_SIGN_RADIOACTIVITY,
1341 EL_EMC_STEEL_WALL_1,
1342 EL_EMC_STEEL_WALL_2,
1343 EL_EMC_STEEL_WALL_3,
1344 EL_EMC_STEEL_WALL_4,
1358 static int ep_massive_num = sizeof(ep_massive)/sizeof(int);
1360 static int ep_slippery[] =
1395 static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
1397 static int ep_enemy[] =
1410 static int ep_enemy_num = sizeof(ep_enemy)/sizeof(int);
1412 static int ep_mauer[] =
1462 EL_EMC_STEEL_WALL_1,
1463 EL_EMC_STEEL_WALL_2,
1464 EL_EMC_STEEL_WALL_3,
1465 EL_EMC_STEEL_WALL_4,
1475 static int ep_mauer_num = sizeof(ep_mauer)/sizeof(int);
1477 static int ep_can_fall[] =
1492 EL_MAGIC_WALL_BD_FULL,
1503 static int ep_can_fall_num = sizeof(ep_can_fall)/sizeof(int);
1505 static int ep_can_smash[] =
1536 static int ep_can_smash_num = sizeof(ep_can_smash)/sizeof(int);
1538 static int ep_can_change[] =
1549 static int ep_can_change_num = sizeof(ep_can_change)/sizeof(int);
1551 static int ep_can_move[] =
1571 static int ep_can_move_num = sizeof(ep_can_move)/sizeof(int);
1573 static int ep_could_move[] =
1596 static int ep_could_move_num = sizeof(ep_could_move)/sizeof(int);
1598 static int ep_dont_touch[] =
1605 static int ep_dont_touch_num = sizeof(ep_dont_touch)/sizeof(int);
1607 static int ep_dont_go_to[] =
1625 static int ep_dont_go_to_num = sizeof(ep_dont_go_to)/sizeof(int);
1627 static int ep_mampf2[] =
1652 static int ep_mampf2_num = sizeof(ep_mampf2)/sizeof(int);
1654 static int ep_bd_element[] =
1663 EL_MAGIC_WALL_BD_OFF,
1681 static int ep_bd_element_num = sizeof(ep_bd_element)/sizeof(int);
1683 static int ep_sb_element[] =
1688 EL_SOKOBAN_FELD_LEER,
1689 EL_SOKOBAN_FELD_VOLL,
1693 static int ep_sb_element_num = sizeof(ep_sb_element)/sizeof(int);
1695 static int ep_gem[] =
1705 static int ep_gem_num = sizeof(ep_gem)/sizeof(int);
1707 static int ep_inactive[] =
1744 EL_DYNAMITE_INACTIVE,
1756 EL_SOKOBAN_FELD_LEER,
1757 EL_SOKOBAN_FELD_VOLL,
1767 EL_MAGIC_WALL_BD_OFF,
1768 EL_MAGIC_WALL_BD_DEAD,
1804 EL_BELT1_SWITCH_LEFT,
1805 EL_BELT1_SWITCH_MIDDLE,
1806 EL_BELT1_SWITCH_RIGHT,
1807 EL_BELT2_SWITCH_LEFT,
1808 EL_BELT2_SWITCH_MIDDLE,
1809 EL_BELT2_SWITCH_RIGHT,
1810 EL_BELT3_SWITCH_LEFT,
1811 EL_BELT3_SWITCH_MIDDLE,
1812 EL_BELT3_SWITCH_RIGHT,
1813 EL_BELT4_SWITCH_LEFT,
1814 EL_BELT4_SWITCH_MIDDLE,
1815 EL_BELT4_SWITCH_RIGHT,
1816 EL_SIGN_EXCLAMATION,
1817 EL_SIGN_RADIOACTIVITY,
1829 EL_EMC_STEEL_WALL_1,
1830 EL_EMC_STEEL_WALL_2,
1831 EL_EMC_STEEL_WALL_3,
1832 EL_EMC_STEEL_WALL_4,
1842 static int ep_inactive_num = sizeof(ep_inactive)/sizeof(int);
1844 static int ep_explosive[] =
1848 EL_DYNAMITE_INACTIVE,
1849 EL_DYNABOMB_ACTIVE_1,
1850 EL_DYNABOMB_ACTIVE_2,
1851 EL_DYNABOMB_ACTIVE_3,
1852 EL_DYNABOMB_ACTIVE_4,
1869 static int ep_explosive_num = sizeof(ep_explosive)/sizeof(int);
1871 static int ep_mampf3[] =
1882 static int ep_mampf3_num = sizeof(ep_mampf3)/sizeof(int);
1884 static int ep_pushable[] =
1891 EL_SOKOBAN_FELD_VOLL,
1901 static int ep_pushable_num = sizeof(ep_pushable)/sizeof(int);
1903 static int ep_player[] =
1911 static int ep_player_num = sizeof(ep_player)/sizeof(int);
1913 static int ep_has_content[] =
1921 static int ep_has_content_num = sizeof(ep_has_content)/sizeof(int);
1923 static int ep_eatable[] =
1931 static int ep_eatable_num = sizeof(ep_eatable)/sizeof(int);
1933 static int ep_sp_element[] =
1975 /* additional elements that appeared in newer Supaplex levels */
1977 /* more than one murphy in a level results in an inactive clone */
1980 static int ep_sp_element_num = sizeof(ep_sp_element)/sizeof(int);
1982 static int ep_quick_gate[] =
2006 static int ep_quick_gate_num = sizeof(ep_quick_gate)/sizeof(int);
2008 static int ep_over_player[] =
2033 static int ep_over_player_num = sizeof(ep_over_player)/sizeof(int);
2035 static int ep_active_bomb[] =
2038 EL_DYNABOMB_ACTIVE_1,
2039 EL_DYNABOMB_ACTIVE_2,
2040 EL_DYNABOMB_ACTIVE_3,
2041 EL_DYNABOMB_ACTIVE_4
2043 static int ep_active_bomb_num = sizeof(ep_active_bomb)/sizeof(int);
2045 static int ep_belt[] =
2060 static int ep_belt_num = sizeof(ep_belt)/sizeof(int);
2062 static int ep_belt_switch[] =
2064 EL_BELT1_SWITCH_LEFT,
2065 EL_BELT1_SWITCH_MIDDLE,
2066 EL_BELT1_SWITCH_RIGHT,
2067 EL_BELT2_SWITCH_LEFT,
2068 EL_BELT2_SWITCH_MIDDLE,
2069 EL_BELT2_SWITCH_RIGHT,
2070 EL_BELT3_SWITCH_LEFT,
2071 EL_BELT3_SWITCH_MIDDLE,
2072 EL_BELT3_SWITCH_RIGHT,
2073 EL_BELT4_SWITCH_LEFT,
2074 EL_BELT4_SWITCH_MIDDLE,
2075 EL_BELT4_SWITCH_RIGHT,
2077 static int ep_belt_switch_num = sizeof(ep_belt_switch)/sizeof(int);
2079 static int ep_tube[] =
2093 static int ep_tube_num = sizeof(ep_tube)/sizeof(int);
2095 static long ep1_bit[] =
2129 static long ep2_bit[] =
2135 static int *ep1_array[] =
2169 static int *ep2_array[] =
2175 static int *ep1_num[] =
2202 &ep_has_content_num,
2206 &ep_over_player_num,
2209 static int *ep2_num[] =
2212 &ep_belt_switch_num,
2215 static int num_properties1 = sizeof(ep1_num)/sizeof(int *);
2216 static int num_properties2 = sizeof(ep2_num)/sizeof(int *);
2218 for(i=0; i<MAX_ELEMENTS; i++)
2220 Elementeigenschaften1[i] = 0;
2221 Elementeigenschaften2[i] = 0;
2224 for(i=0; i<num_properties1; i++)
2225 for(j=0; j<*(ep1_num[i]); j++)
2226 Elementeigenschaften1[(ep1_array[i])[j]] |= ep1_bit[i];
2227 for(i=0; i<num_properties2; i++)
2228 for(j=0; j<*(ep2_num[i]); j++)
2229 Elementeigenschaften2[(ep2_array[i])[j]] |= ep2_bit[i];
2231 for(i=EL_CHAR_START; i<=EL_CHAR_END; i++)
2232 Elementeigenschaften1[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
2235 void CloseAllAndExit(int exit_value)
2239 #ifdef USE_SDL_LIBRARY
2241 FreeSounds(NUM_SOUNDS);
2243 if (sound_process_id)
2246 kill(sound_process_id, SIGTERM);
2247 FreeSounds(NUM_SOUNDS);
2251 for(i=0; i<NUM_BITMAPS; i++)
2255 #ifdef USE_XPM_LIBRARY
2256 if (i < NUM_PICTURES) /* XPM pictures */
2258 XFreeColors(display,DefaultColormap(display,screen),
2259 xpm_att[i].pixels,xpm_att[i].npixels,0);
2260 XpmFreeAttributes(&xpm_att[i]);
2264 #ifdef USE_SDL_LIBRARY
2265 SDL_FreeSurface(pix[i]);
2267 XFreePixmap(display,pix[i]);
2271 #ifdef USE_SDL_LIBRARY
2272 SDL_FreeSurface(pix_masked[i]);
2275 XFreePixmap(display,clipmask[i]);
2277 XFreeGC(display, clip_gc[i]);
2281 #ifdef USE_SDL_LIBRARY
2282 KeyboardAutoRepeatOn();
2285 XFreeGC(display, gc);
2289 KeyboardAutoRepeatOn();
2290 XCloseDisplay(display);
2294 #if defined(MSDOS) || defined(WIN32)