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 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 /* tool button identifiers */
35 #define TOOL_CTRL_ID_YES 0
36 #define TOOL_CTRL_ID_NO 1
37 #define TOOL_CTRL_ID_CONFIRM 2
38 #define TOOL_CTRL_ID_PLAYER_1 3
39 #define TOOL_CTRL_ID_PLAYER_2 4
40 #define TOOL_CTRL_ID_PLAYER_3 5
41 #define TOOL_CTRL_ID_PLAYER_4 6
43 #define NUM_TOOL_BUTTONS 7
45 /* forward declaration for internal use */
46 static int getGraphicAnimationPhase(int, int, int);
47 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
49 static void UnmapToolButtons();
50 static void HandleToolButtons(struct GadgetInfo *);
52 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
53 static int request_gadget_id = -1;
55 void SetDrawtoField(int mode)
57 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
68 drawto_field = fieldbuffer;
70 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
81 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
88 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
90 if (setup.direct_draw && game_status == PLAYING)
91 redraw_mask &= ~REDRAW_MAIN;
93 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
94 redraw_mask |= REDRAW_FIELD;
96 if (redraw_mask & REDRAW_FIELD)
97 redraw_mask &= ~REDRAW_TILES;
102 /* synchronize X11 graphics at this point; if we would synchronize the
103 display immediately after the buffer switching (after the XFlush),
104 this could mean that we have to wait for the graphics to complete,
105 although we could go on doing calculations for the next frame */
107 XSync(display, FALSE);
109 if (redraw_mask & REDRAW_ALL)
111 XCopyArea(display, backbuffer, window, gc,
112 0, 0, WIN_XSIZE, WIN_YSIZE,
117 if (redraw_mask & REDRAW_FIELD)
119 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
121 XCopyArea(display, backbuffer, window, gc,
122 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
127 int fx = FX, fy = FY;
129 if (setup.soft_scrolling)
131 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
132 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
135 if (setup.soft_scrolling ||
136 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
137 ABS(ScreenMovPos) == ScrollStepSize ||
138 redraw_tiles > REDRAWTILES_THRESHOLD)
140 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
144 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
146 (setup.soft_scrolling ?
147 "setup.soft_scrolling" :
148 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
149 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
150 ABS(ScreenGfxPos) == ScrollStepSize ?
151 "ABS(ScreenGfxPos) == ScrollStepSize" :
152 "redraw_tiles > REDRAWTILES_THRESHOLD"));
157 redraw_mask &= ~REDRAW_MAIN;
160 if (redraw_mask & REDRAW_DOORS)
162 if (redraw_mask & REDRAW_DOOR_1)
163 XCopyArea(display, backbuffer, window, gc,
164 DX, DY, DXSIZE, DYSIZE,
166 if (redraw_mask & REDRAW_DOOR_2)
168 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
169 XCopyArea(display,backbuffer,window,gc,
170 VX,VY, VXSIZE,VYSIZE,
174 if (redraw_mask & REDRAW_VIDEO_1)
175 XCopyArea(display,backbuffer,window,gc,
176 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
177 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
178 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
179 if (redraw_mask & REDRAW_VIDEO_2)
180 XCopyArea(display,backbuffer,window,gc,
181 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
182 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
183 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
184 if (redraw_mask & REDRAW_VIDEO_3)
185 XCopyArea(display,backbuffer,window,gc,
186 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
187 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
188 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
191 if (redraw_mask & REDRAW_DOOR_3)
192 XCopyArea(display, backbuffer, window, gc,
193 EX, EY, EXSIZE, EYSIZE,
195 redraw_mask &= ~REDRAW_DOORS;
198 if (redraw_mask & REDRAW_MICROLEVEL)
200 XCopyArea(display,backbuffer,window,gc,
201 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
202 MICROLEV_XPOS, MICROLEV_YPOS);
203 XCopyArea(display,backbuffer,window,gc,
204 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
205 SX, MICROLABEL_YPOS);
206 redraw_mask &= ~REDRAW_MICROLEVEL;
209 if (redraw_mask & REDRAW_TILES)
211 for(x=0; x<SCR_FIELDX; x++)
212 for(y=0; y<SCR_FIELDY; y++)
213 if (redraw[redraw_x1 + x][redraw_y1 + y])
214 XCopyArea(display, buffer, window, gc,
215 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
216 SX + x * TILEX, SY + y * TILEY);
221 for(x=0; x<MAX_BUF_XSIZE; x++)
222 for(y=0; y<MAX_BUF_YSIZE; y++)
231 long fading_delay = 300;
233 if (setup.fading && (redraw_mask & REDRAW_FIELD))
240 XFillRectangle(display,window,gc,
241 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
244 for(i=0;i<2*FULL_SYSIZE;i++)
246 for(y=0;y<FULL_SYSIZE;y++)
248 XCopyArea(display,backbuffer,window,gc,
249 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
257 for(i=1;i<FULL_SYSIZE;i+=2)
258 XCopyArea(display,backbuffer,window,gc,
259 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
265 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
266 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
267 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
271 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
272 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
273 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
277 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
278 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
279 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
283 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
284 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
285 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
289 redraw_mask &= ~REDRAW_MAIN;
298 XFillRectangle(display, backbuffer, gc,
299 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
301 if (setup.soft_scrolling && game_status == PLAYING)
303 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
304 SetDrawtoField(DRAW_BUFFERED);
307 SetDrawtoField(DRAW_BACKBUFFER);
309 if (setup.direct_draw && game_status == PLAYING)
311 XFillRectangle(display, window, gc,
312 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
313 SetDrawtoField(DRAW_DIRECT);
316 redraw_mask |= REDRAW_FIELD;
319 int getFontWidth(int font_size, int font_type)
321 return (font_size == FS_BIG ? FONT1_XSIZE :
322 font_type == FC_SPECIAL1 ? FONT3_XSIZE :
323 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
324 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
328 int getFontHeight(int font_size, int font_type)
330 return (font_size == FS_BIG ? FONT1_YSIZE :
331 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
332 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
333 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
337 void DrawTextFCentered(int y, int font_type, char *format, ...)
339 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
340 int font_width = getFontWidth(FS_SMALL, font_type);
343 va_start(ap, format);
344 vsprintf(buffer, format, ap);
347 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
348 buffer, FS_SMALL, font_type);
351 void DrawTextF(int x, int y, int font_type, char *format, ...)
353 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
356 va_start(ap, format);
357 vsprintf(buffer, format, ap);
360 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
363 void DrawText(int x, int y, char *text, int font_size, int font_type)
365 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
368 redraw_mask |= REDRAW_FIELD;
370 redraw_mask |= REDRAW_DOOR_1;
373 void DrawTextExt(Drawable d, GC gc, int x, int y,
374 char *text, int font_size, int font_type)
376 int font_width, font_height, font_start;
378 boolean print_inverse = FALSE;
380 if (font_size != FS_SMALL && font_size != FS_BIG)
381 font_size = FS_SMALL;
382 if (font_type < FC_RED || font_type > FC_SPECIAL3)
385 font_width = getFontWidth(font_size, font_type);
386 font_height = getFontHeight(font_size, font_type);
388 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
389 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
390 FONT_LINES_PER_FONT);
392 if (font_type == FC_SPECIAL3)
393 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
399 if (c == '~' && font_size == FS_SMALL)
401 print_inverse = TRUE;
405 if (c >= 'a' && c <= 'z')
407 else if (c == 'ä' || c == 'Ä')
409 else if (c == 'ö' || c == 'Ö')
411 else if (c == 'ü' || c == 'Ü')
414 if (c >= 32 && c <= 95)
416 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
417 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
418 int dest_x = x, dest_y = y;
422 XCopyArea(display, pix[font_pixmap], d, gc,
423 FONT_CHARS_PER_LINE * font_width,
424 3 * font_height + font_start,
425 font_width, font_height, x, y);
427 XSetClipOrigin(display, clip_gc[font_pixmap],
428 dest_x - src_x, dest_y - src_y);
429 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
430 0, 0, font_width, font_height, dest_x, dest_y);
433 XCopyArea(display, pix[font_pixmap], d, gc,
434 src_x, src_y, font_width, font_height, dest_x, dest_y);
441 void DrawAllPlayers()
445 for(i=0; i<MAX_PLAYERS; i++)
446 if (stored_player[i].active)
447 DrawPlayer(&stored_player[i]);
450 void DrawPlayerField(int x, int y)
452 if (!IS_PLAYER(x, y))
455 DrawPlayer(PLAYERINFO(x, y));
458 void DrawPlayer(struct PlayerInfo *player)
460 int jx = player->jx, jy = player->jy;
461 int last_jx = player->last_jx, last_jy = player->last_jy;
462 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
463 int sx = SCREENX(jx), sy = SCREENY(jy);
464 int sxx = 0, syy = 0;
465 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
467 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
469 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
473 if (!IN_LEV_FIELD(jx,jy))
475 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
476 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
477 printf("DrawPlayerField(): This should never happen!\n");
482 if (element == EL_EXPLODING)
485 /* draw things in the field the player is leaving, if needed */
487 if (player_is_moving)
489 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
491 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
492 DrawLevelFieldThruMask(last_jx, last_jy);
494 else if (last_element == EL_DYNAMITE_ACTIVE)
495 DrawDynamite(last_jx, last_jy);
497 DrawLevelField(last_jx, last_jy);
499 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
503 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
504 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
506 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
509 DrawLevelField(next_jx, next_jy);
513 if (!IN_SCR_FIELD(sx, sy))
516 if (setup.direct_draw)
517 SetDrawtoField(DRAW_BUFFERED);
519 /* draw things behind the player, if needed */
522 DrawLevelElement(jx, jy, Store[jx][jy]);
523 else if (!IS_ACTIVE_BOMB(element))
524 DrawLevelField(jx, jy);
526 /* draw player himself */
528 if (game.emulation == EMU_SUPAPLEX)
530 static int last_dir = MV_LEFT;
531 int action = (player->programmed_action ? player->programmed_action :
533 boolean action_moving =
535 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
536 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
538 graphic = GFX_SP_MURPHY;
542 if (player->MovDir == MV_LEFT)
543 graphic = GFX_MURPHY_PUSH_LEFT;
544 else if (player->MovDir == MV_RIGHT)
545 graphic = GFX_MURPHY_PUSH_RIGHT;
546 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
547 graphic = GFX_MURPHY_PUSH_LEFT;
548 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
549 graphic = GFX_MURPHY_PUSH_RIGHT;
551 else if (player->snapped)
553 if (player->MovDir == MV_LEFT)
554 graphic = GFX_MURPHY_SNAP_LEFT;
555 else if (player->MovDir == MV_RIGHT)
556 graphic = GFX_MURPHY_SNAP_RIGHT;
557 else if (player->MovDir == MV_UP)
558 graphic = GFX_MURPHY_SNAP_UP;
559 else if (player->MovDir == MV_DOWN)
560 graphic = GFX_MURPHY_SNAP_DOWN;
562 else if (action_moving)
564 if (player->MovDir == MV_LEFT)
565 graphic = GFX_MURPHY_GO_LEFT;
566 else if (player->MovDir == MV_RIGHT)
567 graphic = GFX_MURPHY_GO_RIGHT;
568 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
569 graphic = GFX_MURPHY_GO_LEFT;
570 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
571 graphic = GFX_MURPHY_GO_RIGHT;
573 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
576 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
577 last_dir = player->MovDir;
581 if (player->MovDir == MV_LEFT)
583 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
584 else if (player->MovDir == MV_RIGHT)
586 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
587 else if (player->MovDir == MV_UP)
588 graphic = GFX_SPIELER1_UP;
589 else /* MV_DOWN || MV_NO_MOVING */
590 graphic = GFX_SPIELER1_DOWN;
592 graphic += player->index_nr * 3 * HEROES_PER_LINE;
593 graphic += player->Frame;
598 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
599 sxx = player->GfxPos;
601 syy = player->GfxPos;
604 if (!setup.soft_scrolling && ScreenMovPos)
607 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
609 if (FORCE_FIELD_ON(player))
610 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, GFX_FUNKELN_BLAU,
611 3, 8, ANIM_OSCILLATE);
613 if (player->Pushing && player->GfxPos)
615 int px = SCREENX(next_jx), py = SCREENY(next_jy);
617 if (element == EL_SOKOBAN_FELD_LEER ||
618 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
619 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
623 int element = Feld[next_jx][next_jy];
624 int graphic = el2gfx(element);
626 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
628 int phase = (player->GfxPos / (TILEX / 4));
630 if (player->MovDir == MV_LEFT)
633 graphic += (phase + 4) % 4;
636 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
640 /* draw things in front of player (active dynamite or dynabombs) */
642 if (IS_ACTIVE_BOMB(element))
644 graphic = el2gfx(element);
646 if (element == EL_DYNAMITE_ACTIVE)
648 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
653 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
657 if (game.emulation == EMU_SUPAPLEX)
658 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
660 DrawGraphicThruMask(sx, sy, graphic + phase);
663 if (player_is_moving && last_element == EL_EXPLODING)
665 int phase = Frame[last_jx][last_jy];
669 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
670 GFX_EXPLOSION + ((phase - 1) / delay - 1));
673 /* draw elements that stay over the player */
674 /* handle the field the player is leaving ... */
675 if (player_is_moving && IS_OVER_PLAYER(last_element))
676 DrawLevelField(last_jx, last_jy);
677 /* ... and the field the player is entering */
678 if (IS_OVER_PLAYER(element))
679 DrawLevelField(jx, jy);
681 if (setup.direct_draw)
683 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
684 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
685 int x_size = TILEX * (1 + ABS(jx - last_jx));
686 int y_size = TILEY * (1 + ABS(jy - last_jy));
688 XCopyArea(display, drawto_field, window, gc,
689 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
690 SetDrawtoField(DRAW_DIRECT);
693 MarkTileDirty(sx,sy);
696 static int getGraphicAnimationPhase(int frames, int delay, int mode)
700 if (mode == ANIM_OSCILLATE)
702 int max_anim_frames = 2 * frames - 2;
703 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
704 phase = (phase < frames ? phase : max_anim_frames - phase);
707 phase = (FrameCounter % (delay * frames)) / delay;
709 if (mode == ANIM_REVERSE)
715 void DrawGraphicAnimationExt(int x, int y, int graphic,
716 int frames, int delay, int mode, int mask_mode)
718 int phase = getGraphicAnimationPhase(frames, delay, mode);
720 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
722 if (mask_mode == USE_MASKING)
723 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
725 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
729 void DrawGraphicAnimation(int x, int y, int graphic,
730 int frames, int delay, int mode)
732 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
735 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
736 int frames, int delay, int mode)
738 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
741 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
744 int frames, int delay,
747 int phase = getGraphicAnimationPhase(frames, delay, mode);
749 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
752 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
754 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
756 graphic -= GFX_START_ROCKSSCREEN;
757 *pixmap_nr = PIX_BACK;
758 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
759 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
761 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
763 graphic -= GFX_START_ROCKSHEROES;
764 *pixmap_nr = PIX_HEROES;
765 *x = (graphic % HEROES_PER_LINE) * TILEX;
766 *y = (graphic / HEROES_PER_LINE) * TILEY;
768 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
770 graphic -= GFX_START_ROCKSSP;
772 *x = (graphic % SP_PER_LINE) * TILEX;
773 *y = (graphic / SP_PER_LINE) * TILEY;
775 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
777 graphic -= GFX_START_ROCKSDC;
779 *x = (graphic % DC_PER_LINE) * TILEX;
780 *y = (graphic / DC_PER_LINE) * TILEY;
782 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
784 graphic -= GFX_START_ROCKSFONT;
785 *pixmap_nr = PIX_BIGFONT;
786 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
787 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
788 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
798 void DrawGraphic(int x, int y, int graphic)
801 if (!IN_SCR_FIELD(x,y))
803 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
804 printf("DrawGraphic(): This should never happen!\n");
809 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
813 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
818 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
819 XCopyArea(display, pix[pixmap_nr], d, gc,
820 src_x, src_y, TILEX, TILEY, x, y);
823 void DrawGraphicThruMask(int x, int y, int graphic)
826 if (!IN_SCR_FIELD(x,y))
828 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
829 printf("DrawGraphicThruMask(): This should never happen!\n");
834 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
838 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
846 if (graphic == GFX_LEERRAUM)
849 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
850 src_pixmap = pix[pixmap_nr];
851 drawing_gc = clip_gc[pixmap_nr];
853 if (tile_clipmask[tile] != None)
855 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
856 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
857 XCopyArea(display, src_pixmap, d, tile_clip_gc,
858 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
863 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
866 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
867 XCopyArea(display, src_pixmap, d, drawing_gc,
868 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
872 void DrawMiniGraphic(int x, int y, int graphic)
874 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
875 MarkTileDirty(x/2, y/2);
878 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
880 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
882 graphic -= GFX_START_ROCKSSCREEN;
883 *pixmap = pix[PIX_BACK];
884 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
885 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
887 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
889 graphic -= GFX_START_ROCKSSP;
890 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
891 *pixmap = pix[PIX_SP];
892 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
893 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
895 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
897 graphic -= GFX_START_ROCKSDC;
898 *pixmap = pix[PIX_DC];
899 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
900 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
902 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
904 graphic -= GFX_START_ROCKSFONT;
905 *pixmap = pix[PIX_SMALLFONT];
906 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
907 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
908 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
912 *pixmap = pix[PIX_SP];
918 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
923 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
924 XCopyArea(display, pixmap, d, gc,
925 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
928 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
929 int cut_mode, int mask_mode)
931 int width = TILEX, height = TILEY;
933 int src_x, src_y, dest_x, dest_y;
941 DrawGraphic(x, y, graphic);
945 if (dx || dy) /* Verschiebung der Grafik? */
947 if (x < BX1) /* Element kommt von links ins Bild */
954 else if (x > BX2) /* Element kommt von rechts ins Bild */
960 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
966 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
968 else if (dx) /* allg. Bewegung in x-Richtung */
969 MarkTileDirty(x + SIGN(dx), y);
971 if (y < BY1) /* Element kommt von oben ins Bild */
973 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
981 else if (y > BY2) /* Element kommt von unten ins Bild */
987 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
993 else if (dy > 0 && cut_mode == CUT_ABOVE)
995 if (y == BY2) /* Element unterhalb des Bildes */
1001 MarkTileDirty(x, y + 1);
1002 } /* Element verläßt unten das Bild */
1003 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1005 else if (dy) /* allg. Bewegung in y-Richtung */
1006 MarkTileDirty(x, y + SIGN(dy));
1009 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
1010 src_pixmap = pix[pixmap_nr];
1011 drawing_gc = clip_gc[pixmap_nr];
1016 dest_x = FX + x * TILEX + dx;
1017 dest_y = FY + y * TILEY + dy;
1020 if (!IN_SCR_FIELD(x,y))
1022 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1023 printf("DrawGraphicShifted(): This should never happen!\n");
1028 if (mask_mode == USE_MASKING)
1030 if (tile_clipmask[tile] != None)
1032 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1033 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1034 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1035 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1040 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1043 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1044 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1045 src_x, src_y, width, height, dest_x, dest_y);
1049 XCopyArea(display, src_pixmap, drawto_field, gc,
1050 src_x, src_y, width, height, dest_x, dest_y);
1055 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1058 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1061 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1062 int cut_mode, int mask_mode)
1064 int ux = LEVELX(x), uy = LEVELY(y);
1065 int graphic = el2gfx(element);
1066 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1067 int phase4 = phase8 / 2;
1068 int phase2 = phase8 / 4;
1069 int dir = MovDir[ux][uy];
1071 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1073 graphic += 4 * !phase2;
1077 else if (dir == MV_LEFT)
1079 else if (dir == MV_DOWN)
1082 else if (element == EL_SP_SNIKSNAK)
1085 graphic = GFX_SP_SNIKSNAK_LEFT;
1086 else if (dir == MV_RIGHT)
1087 graphic = GFX_SP_SNIKSNAK_RIGHT;
1088 else if (dir == MV_UP)
1089 graphic = GFX_SP_SNIKSNAK_UP;
1091 graphic = GFX_SP_SNIKSNAK_DOWN;
1093 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1095 else if (element == EL_SP_ELECTRON)
1097 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1099 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1100 element == EL_SCHWEIN || element == EL_DRACHE)
1103 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1104 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1105 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1106 else if (dir == MV_RIGHT)
1107 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1108 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1109 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1110 else if (dir == MV_UP)
1111 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1112 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1113 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1115 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1116 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1117 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1121 else if (element == EL_SONDE)
1123 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1125 else if (element == EL_SALZSAEURE)
1127 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1129 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1133 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1134 IS_GEM(element)) && !cut_mode)
1136 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1138 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1141 graphic += (4 - phase4) % 4;
1142 else if (dir == MV_RIGHT)
1145 graphic += phase2 * 2;
1147 else if (element != EL_SP_INFOTRON)
1151 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1152 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1154 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1156 else if (IS_AMOEBOID(element))
1158 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1159 graphic += (x + 2 * y + 4) % 4;
1161 else if (element == EL_MAUER_LEBT)
1163 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1165 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1166 links_massiv = TRUE;
1167 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1168 rechts_massiv = TRUE;
1170 if (links_massiv && rechts_massiv)
1171 graphic = GFX_MAUERWERK;
1172 else if (links_massiv)
1173 graphic = GFX_MAUER_R;
1174 else if (rechts_massiv)
1175 graphic = GFX_MAUER_L;
1177 else if ((element == EL_INVISIBLE_STEEL ||
1178 element == EL_UNSICHTBAR ||
1179 element == EL_SAND_INVISIBLE) && game.light_time_left)
1181 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1182 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1183 GFX_SAND_INVISIBLE_ON);
1187 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1188 else if (mask_mode == USE_MASKING)
1189 DrawGraphicThruMask(x, y, graphic);
1191 DrawGraphic(x, y, graphic);
1194 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1195 int cut_mode, int mask_mode)
1197 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1198 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1199 cut_mode, mask_mode);
1202 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1205 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1208 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1211 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1214 void DrawScreenElementThruMask(int x, int y, int element)
1216 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1219 void DrawLevelElementThruMask(int x, int y, int element)
1221 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1224 void DrawLevelFieldThruMask(int x, int y)
1226 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1229 void ErdreichAnbroeckeln(int x, int y)
1231 int i, width, height, cx,cy;
1232 int ux = LEVELX(x), uy = LEVELY(y);
1233 int element, graphic;
1235 static int xy[4][2] =
1243 if (!IN_LEV_FIELD(ux, uy))
1246 element = Feld[ux][uy];
1248 if (element == EL_ERDREICH || element == EL_LANDMINE)
1250 if (!IN_SCR_FIELD(x, y))
1253 graphic = GFX_ERDENRAND;
1259 uxx = ux + xy[i][0];
1260 uyy = uy + xy[i][1];
1261 if (!IN_LEV_FIELD(uxx, uyy))
1264 element = Feld[uxx][uyy];
1266 if (element == EL_ERDREICH || element == EL_LANDMINE)
1269 if (i == 1 || i == 2)
1273 cx = (i == 2 ? TILEX - snip : 0);
1281 cy = (i == 3 ? TILEY - snip : 0);
1284 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1285 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1286 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1287 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1290 MarkTileDirty(x, y);
1294 graphic = GFX_ERDENRAND;
1298 int xx, yy, uxx, uyy;
1302 uxx = ux + xy[i][0];
1303 uyy = uy + xy[i][1];
1305 if (!IN_LEV_FIELD(uxx, uyy) ||
1306 (Feld[uxx][uyy] != EL_ERDREICH && Feld[uxx][uyy] != EL_LANDMINE) ||
1307 !IN_SCR_FIELD(xx, yy))
1310 if (i == 1 || i == 2)
1314 cx = (i == 1 ? TILEX - snip : 0);
1322 cy = (i==0 ? TILEY-snip : 0);
1325 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1326 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1327 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1328 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1330 MarkTileDirty(xx, yy);
1335 void DrawScreenElement(int x, int y, int element)
1337 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1338 ErdreichAnbroeckeln(x, y);
1341 void DrawLevelElement(int x, int y, int element)
1343 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1344 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1347 void DrawScreenField(int x, int y)
1349 int ux = LEVELX(x), uy = LEVELY(y);
1352 if (!IN_LEV_FIELD(ux, uy))
1354 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1355 element = EL_LEERRAUM;
1357 element = BorderElement;
1359 DrawScreenElement(x, y, element);
1363 element = Feld[ux][uy];
1365 if (IS_MOVING(ux, uy))
1367 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1368 boolean cut_mode = NO_CUTTING;
1370 if (Store[ux][uy] == EL_MORAST_LEER ||
1371 Store[ux][uy] == EL_SIEB_LEER ||
1372 Store[ux][uy] == EL_SIEB2_LEER ||
1373 Store[ux][uy] == EL_AMOEBE_NASS)
1374 cut_mode = CUT_ABOVE;
1375 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1376 Store[ux][uy] == EL_SIEB_VOLL ||
1377 Store[ux][uy] == EL_SIEB2_VOLL)
1378 cut_mode = CUT_BELOW;
1380 if (cut_mode == CUT_ABOVE)
1381 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1383 DrawScreenElement(x, y, EL_LEERRAUM);
1386 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1388 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1390 if (Store[ux][uy] == EL_SALZSAEURE)
1391 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1393 else if (IS_BLOCKED(ux, uy))
1398 boolean cut_mode = NO_CUTTING;
1400 Blocked2Moving(ux, uy, &oldx, &oldy);
1403 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1404 MovDir[oldx][oldy] == MV_RIGHT);
1406 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1407 Store[oldx][oldy] == EL_SIEB_LEER ||
1408 Store[oldx][oldy] == EL_SIEB2_LEER ||
1409 Store[oldx][oldy] == EL_AMOEBE_NASS)
1410 cut_mode = CUT_ABOVE;
1412 DrawScreenElement(x, y, EL_LEERRAUM);
1413 element = Feld[oldx][oldy];
1416 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1418 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1420 else if (IS_DRAWABLE(element))
1421 DrawScreenElement(x, y, element);
1423 DrawScreenElement(x, y, EL_LEERRAUM);
1426 void DrawLevelField(int x, int y)
1428 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1429 DrawScreenField(SCREENX(x), SCREENY(y));
1430 else if (IS_MOVING(x, y))
1434 Moving2Blocked(x, y, &newx, &newy);
1435 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1436 DrawScreenField(SCREENX(newx), SCREENY(newy));
1438 else if (IS_BLOCKED(x, y))
1442 Blocked2Moving(x, y, &oldx, &oldy);
1443 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1444 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1448 void DrawMiniElement(int x, int y, int element)
1454 DrawMiniGraphic(x, y, -1);
1458 graphic = el2gfx(element);
1459 DrawMiniGraphic(x, y, graphic);
1462 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1464 int x = sx + scroll_x, y = sy + scroll_y;
1466 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1467 DrawMiniElement(sx, sy, EL_LEERRAUM);
1468 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1469 DrawMiniElement(sx, sy, Feld[x][y]);
1472 int steel_type, steel_position;
1475 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1476 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1477 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1478 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1479 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1480 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1483 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1484 steel_position = (x == -1 && y == -1 ? 0 :
1485 x == lev_fieldx && y == -1 ? 1 :
1486 x == -1 && y == lev_fieldy ? 2 :
1487 x == lev_fieldx && y == lev_fieldy ? 3 :
1488 x == -1 || x == lev_fieldx ? 4 :
1489 y == -1 || y == lev_fieldy ? 5 : -1);
1491 if (steel_position != -1)
1492 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1496 void DrawMicroElement(int xpos, int ypos, int element)
1500 if (element == EL_LEERRAUM)
1503 graphic = el2gfx(element);
1505 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1507 graphic -= GFX_START_ROCKSSP;
1508 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1509 XCopyArea(display, pix[PIX_SP], drawto, gc,
1510 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1511 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1512 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1514 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1516 graphic -= GFX_START_ROCKSDC;
1517 XCopyArea(display, pix[PIX_DC], drawto, gc,
1518 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1519 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1520 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1523 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1524 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1525 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1526 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1535 for(x=BX1; x<=BX2; x++)
1536 for(y=BY1; y<=BY2; y++)
1537 DrawScreenField(x, y);
1539 redraw_mask |= REDRAW_FIELD;
1542 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1546 for(x=0; x<size_x; x++)
1547 for(y=0; y<size_y; y++)
1548 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1550 redraw_mask |= REDRAW_FIELD;
1553 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1557 XFillRectangle(display, drawto, gc,
1558 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1560 if (lev_fieldx < STD_LEV_FIELDX)
1561 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1562 if (lev_fieldy < STD_LEV_FIELDY)
1563 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1565 xpos += MICRO_TILEX;
1566 ypos += MICRO_TILEY;
1568 for(x=-1; x<=STD_LEV_FIELDX; x++)
1570 for(y=-1; y<=STD_LEV_FIELDY; y++)
1572 int lx = from_x + x, ly = from_y + y;
1574 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1575 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1577 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1578 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1583 redraw_mask |= REDRAW_MICROLEVEL;
1586 #define MICROLABEL_EMPTY 0
1587 #define MICROLABEL_LEVEL_NAME 1
1588 #define MICROLABEL_CREATED_BY 2
1589 #define MICROLABEL_LEVEL_AUTHOR 3
1590 #define MICROLABEL_IMPORTED_FROM 4
1591 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1593 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1595 static void DrawMicroLevelLabelExt(int mode)
1597 char label_text[MAX_MICROLABEL_SIZE + 1];
1599 XFillRectangle(display, drawto,gc,
1600 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1602 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1603 mode == MICROLABEL_CREATED_BY ? "created by" :
1604 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1605 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1606 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1607 leveldir[leveldir_nr].imported_from : ""),
1608 MAX_MICROLABEL_SIZE);
1609 label_text[MAX_MICROLABEL_SIZE] = '\0';
1611 if (strlen(label_text) > 0)
1613 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1614 int lypos = MICROLABEL_YPOS;
1616 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1619 redraw_mask |= REDRAW_MICROLEVEL;
1622 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1624 static unsigned long scroll_delay = 0;
1625 static unsigned long label_delay = 0;
1626 static int from_x, from_y, scroll_direction;
1627 static int label_state, label_counter;
1631 from_x = from_y = 0;
1632 scroll_direction = MV_RIGHT;
1636 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1637 DrawMicroLevelLabelExt(label_state);
1639 /* initialize delay counters */
1640 DelayReached(&scroll_delay, 0);
1641 DelayReached(&label_delay, 0);
1646 /* scroll micro level, if needed */
1647 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1648 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1650 switch (scroll_direction)
1656 scroll_direction = MV_UP;
1660 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1663 scroll_direction = MV_DOWN;
1670 scroll_direction = MV_RIGHT;
1674 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1677 scroll_direction = MV_LEFT;
1684 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1687 /* redraw micro level label, if needed */
1688 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1689 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1690 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1691 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1693 int max_label_counter = 23;
1695 if (leveldir[leveldir_nr].imported_from != NULL)
1696 max_label_counter += 14;
1698 label_counter = (label_counter + 1) % max_label_counter;
1699 label_state = (label_counter >= 0 && label_counter <= 7 ?
1700 MICROLABEL_LEVEL_NAME :
1701 label_counter >= 9 && label_counter <= 12 ?
1702 MICROLABEL_CREATED_BY :
1703 label_counter >= 14 && label_counter <= 21 ?
1704 MICROLABEL_LEVEL_AUTHOR :
1705 label_counter >= 23 && label_counter <= 26 ?
1706 MICROLABEL_IMPORTED_FROM :
1707 label_counter >= 28 && label_counter <= 35 ?
1708 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1709 DrawMicroLevelLabelExt(label_state);
1713 int REQ_in_range(int x, int y)
1715 if (y > DY+249 && y < DY+278)
1717 if (x > DX+1 && x < DX+48)
1719 else if (x > DX+51 && x < DX+98)
1725 boolean Request(char *text, unsigned int req_state)
1727 int mx, my, ty, result = -1;
1728 unsigned int old_door_state;
1731 /* pause network game while waiting for request to answer */
1732 if (options.network &&
1733 game_status == PLAYING &&
1734 req_state & REQUEST_WAIT_FOR)
1735 SendToServer_PausePlaying();
1738 old_door_state = GetDoorState();
1742 CloseDoor(DOOR_CLOSE_1);
1744 /* save old door content */
1745 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1746 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1747 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1749 /* clear door drawing field */
1750 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1752 /* write text for request */
1753 for(ty=0; ty<13; ty++)
1761 for(tl=0,tx=0; tx<7; tl++,tx++)
1764 if (!tc || tc == 32)
1775 DrawTextExt(drawto, gc,
1776 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1777 txt, FS_SMALL, FC_YELLOW);
1778 text += tl + (tc == 32 ? 1 : 0);
1781 if (req_state & REQ_ASK)
1783 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1784 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1786 else if (req_state & REQ_CONFIRM)
1788 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1790 else if (req_state & REQ_PLAYER)
1792 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1793 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1794 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1795 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1798 /* copy request gadgets to door backbuffer */
1799 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1800 DX, DY, DXSIZE, DYSIZE,
1801 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1803 OpenDoor(DOOR_OPEN_1);
1809 if (!(req_state & REQUEST_WAIT_FOR))
1812 if (game_status != MAINMENU)
1815 button_status = MB_RELEASED;
1817 request_gadget_id = -1;
1821 if (XPending(display))
1825 XNextEvent(display, &event);
1833 if (event.type == MotionNotify)
1840 if (!XQueryPointer(display, window, &root, &child,
1841 &root_x, &root_y, &win_x, &win_y, &mask))
1847 motion_status = TRUE;
1848 mx = ((XMotionEvent *) &event)->x;
1849 my = ((XMotionEvent *) &event)->y;
1853 motion_status = FALSE;
1854 mx = ((XButtonEvent *) &event)->x;
1855 my = ((XButtonEvent *) &event)->y;
1856 if (event.type==ButtonPress)
1857 button_status = ((XButtonEvent *) &event)->button;
1859 button_status = MB_RELEASED;
1862 /* this sets 'request_gadget_id' */
1863 HandleGadgets(mx, my, button_status);
1865 switch(request_gadget_id)
1867 case TOOL_CTRL_ID_YES:
1870 case TOOL_CTRL_ID_NO:
1873 case TOOL_CTRL_ID_CONFIRM:
1874 result = TRUE | FALSE;
1877 case TOOL_CTRL_ID_PLAYER_1:
1880 case TOOL_CTRL_ID_PLAYER_2:
1883 case TOOL_CTRL_ID_PLAYER_3:
1886 case TOOL_CTRL_ID_PLAYER_4:
1898 switch(XLookupKeysym((XKeyEvent *)&event,
1899 ((XKeyEvent *)&event)->state))
1912 if (req_state & REQ_PLAYER)
1917 key_joystick_mapping = 0;
1921 HandleOtherEvents(&event);
1925 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1927 int joy = AnyJoystick();
1929 if (joy & JOY_BUTTON_1)
1931 else if (joy & JOY_BUTTON_2)
1937 /* don't eat all CPU time */
1941 if (game_status != MAINMENU)
1946 if (!(req_state & REQ_STAY_OPEN))
1948 CloseDoor(DOOR_CLOSE_1);
1950 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1952 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1953 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1954 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1955 OpenDoor(DOOR_OPEN_1);
1962 /* continue network game after request */
1963 if (options.network &&
1964 game_status == PLAYING &&
1965 req_state & REQUEST_WAIT_FOR)
1966 SendToServer_ContinuePlaying();
1972 unsigned int OpenDoor(unsigned int door_state)
1974 unsigned int new_door_state;
1976 if (door_state & DOOR_COPY_BACK)
1978 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1979 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1980 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1981 door_state &= ~DOOR_COPY_BACK;
1984 new_door_state = MoveDoor(door_state);
1986 return(new_door_state);
1989 unsigned int CloseDoor(unsigned int door_state)
1991 unsigned int new_door_state;
1993 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1994 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1995 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1996 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1998 new_door_state = MoveDoor(door_state);
2000 return(new_door_state);
2003 unsigned int GetDoorState()
2005 return(MoveDoor(DOOR_GET_STATE));
2008 unsigned int MoveDoor(unsigned int door_state)
2010 static int door1 = DOOR_OPEN_1;
2011 static int door2 = DOOR_CLOSE_2;
2012 static unsigned long door_delay = 0;
2013 int x, start, stepsize = 2;
2014 unsigned long door_delay_value = stepsize * 5;
2016 if (door_state == DOOR_GET_STATE)
2017 return(door1 | door2);
2019 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2020 door_state &= ~DOOR_OPEN_1;
2021 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2022 door_state &= ~DOOR_CLOSE_1;
2023 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2024 door_state &= ~DOOR_OPEN_2;
2025 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2026 door_state &= ~DOOR_CLOSE_2;
2028 if (setup.quick_doors)
2031 door_delay_value = 0;
2032 StopSound(SND_OEFFNEN);
2035 if (door_state & DOOR_ACTION)
2037 if (!(door_state & DOOR_NO_DELAY))
2038 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2040 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2042 for(x=start; x<=DXSIZE; x+=stepsize)
2044 WaitUntilDelayReached(&door_delay, door_delay_value);
2046 if (door_state & DOOR_ACTION_1)
2048 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2049 int j = (DXSIZE - i) / 3;
2051 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2052 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2053 DXSIZE,DYSIZE - i/2, DX, DY);
2055 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2057 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2058 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2059 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2060 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2061 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2062 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2064 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2065 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2066 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2067 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2068 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2069 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2071 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2072 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2074 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2075 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2077 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2078 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2079 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2080 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2081 DX + DXSIZE - i, DY + 77 + j);
2082 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2083 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2084 DX + DXSIZE - i, DY + 203 + j);
2086 redraw_mask |= REDRAW_DOOR_1;
2089 if (door_state & DOOR_ACTION_2)
2091 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2092 int j = (VXSIZE - i) / 3;
2094 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2095 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2096 VXSIZE, VYSIZE - i/2, VX, VY);
2098 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2100 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2101 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2102 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2103 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2104 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2105 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2106 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2107 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2109 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2110 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2111 VX, VY + VYSIZE / 2 - j);
2112 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2113 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2114 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2115 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2116 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2118 redraw_mask |= REDRAW_DOOR_2;
2123 if (game_status == MAINMENU)
2128 if (setup.quick_doors)
2129 StopSound(SND_OEFFNEN);
2131 if (door_state & DOOR_ACTION_1)
2132 door1 = door_state & DOOR_ACTION_1;
2133 if (door_state & DOOR_ACTION_2)
2134 door2 = door_state & DOOR_ACTION_2;
2136 return (door1 | door2);
2139 void DrawSpecialEditorDoor()
2141 /* draw bigger toolbox window */
2142 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2143 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2145 redraw_mask |= REDRAW_ALL;
2148 void UndrawSpecialEditorDoor()
2150 /* draw normal tape recorder window */
2151 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2152 562, 344, 108, 56, EX - 4, EY - 12);
2154 redraw_mask |= REDRAW_ALL;
2157 int ReadPixel(Drawable d, int x, int y)
2159 XImage *pixel_image;
2160 unsigned long pixel_value;
2162 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2163 pixel_value = XGetPixel(pixel_image, 0, 0);
2165 XDestroyImage(pixel_image);
2170 /* ---------- new tool button stuff ---------------------------------------- */
2172 /* graphic position values for tool buttons */
2173 #define TOOL_BUTTON_YES_XPOS 2
2174 #define TOOL_BUTTON_YES_YPOS 250
2175 #define TOOL_BUTTON_YES_GFX_YPOS 0
2176 #define TOOL_BUTTON_YES_XSIZE 46
2177 #define TOOL_BUTTON_YES_YSIZE 28
2178 #define TOOL_BUTTON_NO_XPOS 52
2179 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2180 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2181 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2182 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2183 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2184 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2185 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2186 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2187 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2188 #define TOOL_BUTTON_PLAYER_XSIZE 30
2189 #define TOOL_BUTTON_PLAYER_YSIZE 30
2190 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2191 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2192 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2193 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2194 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2195 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2196 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2197 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2198 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2199 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2200 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2201 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2202 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2203 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2204 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2205 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2206 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2207 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2208 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2209 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2218 } toolbutton_info[NUM_TOOL_BUTTONS] =
2221 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2222 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2223 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2228 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2229 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2230 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2235 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2236 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2237 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2238 TOOL_CTRL_ID_CONFIRM,
2242 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2243 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2244 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2245 TOOL_CTRL_ID_PLAYER_1,
2249 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2250 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2251 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2252 TOOL_CTRL_ID_PLAYER_2,
2256 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2257 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2258 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2259 TOOL_CTRL_ID_PLAYER_3,
2263 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2264 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2265 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2266 TOOL_CTRL_ID_PLAYER_4,
2271 static void DoNotDisplayInfoText(void *ptr)
2276 void CreateToolButtons()
2280 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2282 Pixmap gd_pixmap = pix[PIX_DOOR];
2283 Pixmap deco_pixmap = None;
2284 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2285 struct GadgetInfo *gi;
2286 unsigned long event_mask;
2287 int gd_xoffset, gd_yoffset;
2288 int gd_x1, gd_x2, gd_y;
2291 event_mask = GD_EVENT_RELEASED;
2293 gd_xoffset = toolbutton_info[i].xpos;
2294 gd_yoffset = toolbutton_info[i].ypos;
2295 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2296 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2297 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2299 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2301 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2302 &deco_pixmap, &deco_x, &deco_y);
2303 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2304 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2307 gi = CreateGadget(GDI_CUSTOM_ID, id,
2308 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2309 GDI_X, DX + toolbutton_info[i].x,
2310 GDI_Y, DY + toolbutton_info[i].y,
2311 GDI_WIDTH, toolbutton_info[i].width,
2312 GDI_HEIGHT, toolbutton_info[i].height,
2313 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2314 GDI_STATE, GD_BUTTON_UNPRESSED,
2315 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2316 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2317 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2318 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2319 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2320 GDI_DECORATION_SHIFTING, 1, 1,
2321 GDI_EVENT_MASK, event_mask,
2322 GDI_CALLBACK_ACTION, HandleToolButtons,
2323 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2327 Error(ERR_EXIT, "cannot create gadget");
2329 tool_gadget[id] = gi;
2333 static void UnmapToolButtons()
2337 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2338 UnmapGadget(tool_gadget[i]);
2341 static void HandleToolButtons(struct GadgetInfo *gi)
2343 request_gadget_id = gi->custom_id;
2346 int el2gfx(int element)
2350 case EL_LEERRAUM: return -1;
2351 case EL_ERDREICH: return GFX_ERDREICH;
2352 case EL_MAUERWERK: return GFX_MAUERWERK;
2353 case EL_FELSBODEN: return GFX_FELSBODEN;
2354 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2355 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2356 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2357 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2358 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2359 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2360 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2361 case EL_SPIELER1: return GFX_SPIELER1;
2362 case EL_SPIELER2: return GFX_SPIELER2;
2363 case EL_SPIELER3: return GFX_SPIELER3;
2364 case EL_SPIELER4: return GFX_SPIELER4;
2365 case EL_KAEFER: return GFX_KAEFER;
2366 case EL_KAEFER_R: return GFX_KAEFER_R;
2367 case EL_KAEFER_O: return GFX_KAEFER_O;
2368 case EL_KAEFER_L: return GFX_KAEFER_L;
2369 case EL_KAEFER_U: return GFX_KAEFER_U;
2370 case EL_FLIEGER: return GFX_FLIEGER;
2371 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2372 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2373 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2374 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2375 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2376 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2377 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2378 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2379 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2380 case EL_FIREFLY: return GFX_FIREFLY;
2381 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2382 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2383 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2384 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2385 case EL_MAMPFER: return GFX_MAMPFER;
2386 case EL_ROBOT: return GFX_ROBOT;
2387 case EL_BETON: return GFX_BETON;
2388 case EL_DIAMANT: return GFX_DIAMANT;
2389 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2390 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2391 case EL_TROPFEN: return GFX_TROPFEN;
2392 case EL_BOMBE: return GFX_BOMBE;
2393 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2394 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2395 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2396 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2397 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2398 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2399 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2400 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2401 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2402 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2403 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2404 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2405 case EL_LIFE: return GFX_LIFE;
2406 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2407 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2408 case EL_BADEWANNE: return GFX_BADEWANNE;
2409 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2410 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2411 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2412 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2413 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2414 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2415 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2416 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2417 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2418 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2419 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2420 case EL_PFORTE1: return GFX_PFORTE1;
2421 case EL_PFORTE2: return GFX_PFORTE2;
2422 case EL_PFORTE3: return GFX_PFORTE3;
2423 case EL_PFORTE4: return GFX_PFORTE4;
2424 case EL_PFORTE1X: return GFX_PFORTE1X;
2425 case EL_PFORTE2X: return GFX_PFORTE2X;
2426 case EL_PFORTE3X: return GFX_PFORTE3X;
2427 case EL_PFORTE4X: return GFX_PFORTE4X;
2428 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2429 case EL_PACMAN: return GFX_PACMAN;
2430 case EL_PACMAN_R: return GFX_PACMAN_R;
2431 case EL_PACMAN_O: return GFX_PACMAN_O;
2432 case EL_PACMAN_L: return GFX_PACMAN_L;
2433 case EL_PACMAN_U: return GFX_PACMAN_U;
2434 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2435 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2436 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2437 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2438 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2439 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2440 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2441 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2442 case EL_MAUER_X: return GFX_MAUER_X;
2443 case EL_MAUER_Y: return GFX_MAUER_Y;
2444 case EL_MAUER_XY: return GFX_MAUER_XY;
2445 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2446 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2447 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2448 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2449 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2450 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2451 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2452 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2453 case EL_MAMPFER2: return GFX_MAMPFER2;
2454 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2455 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2456 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2457 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2458 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2459 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2460 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2461 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2462 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2463 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2464 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2465 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2466 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2467 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2468 case EL_MAULWURF: return GFX_MAULWURF;
2469 case EL_PINGUIN: return GFX_PINGUIN;
2470 case EL_SCHWEIN: return GFX_SCHWEIN;
2471 case EL_DRACHE: return GFX_DRACHE;
2472 case EL_SONDE: return GFX_SONDE;
2473 case EL_PFEIL_L: return GFX_PFEIL_L;
2474 case EL_PFEIL_R: return GFX_PFEIL_R;
2475 case EL_PFEIL_O: return GFX_PFEIL_O;
2476 case EL_PFEIL_U: return GFX_PFEIL_U;
2477 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2478 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2479 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2480 case EL_SP_ZONK: return GFX_SP_ZONK;
2481 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2482 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2483 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2484 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2485 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2486 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2487 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2488 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2489 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2490 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2491 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2492 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2493 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2494 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2495 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2496 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2497 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2498 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2499 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2500 case EL_PEARL: return GFX_PEARL;
2501 case EL_CRYSTAL: return GFX_CRYSTAL;
2502 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2503 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2504 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2505 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2506 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2507 case EL_FORCE_FIELD_PASSIVE:return GFX_FORCE_FIELD_PASSIVE;
2508 case EL_FORCE_FIELD_ACTIVE: return GFX_FORCE_FIELD_ACTIVE;
2509 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2510 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2511 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2512 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2513 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2514 case EL_TIME_GATE: return GFX_TIME_GATE;
2515 case EL_TIME_GATE_WHEEL: return GFX_TIME_GATE_WHEEL;
2516 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2517 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2518 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2519 case EL_BELT1_SWITCH_L: return GFX_BELT1_SWITCH_L;
2520 case EL_BELT1_SWITCH_M: return GFX_BELT1_SWITCH_M;
2521 case EL_BELT1_SWITCH_R: return GFX_BELT1_SWITCH_R;
2522 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2523 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2524 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2525 case EL_BELT2_SWITCH_L: return GFX_BELT2_SWITCH_L;
2526 case EL_BELT2_SWITCH_M: return GFX_BELT2_SWITCH_M;
2527 case EL_BELT2_SWITCH_R: return GFX_BELT2_SWITCH_R;
2528 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2529 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2530 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2531 case EL_BELT3_SWITCH_L: return GFX_BELT3_SWITCH_L;
2532 case EL_BELT3_SWITCH_M: return GFX_BELT3_SWITCH_M;
2533 case EL_BELT3_SWITCH_R: return GFX_BELT3_SWITCH_R;
2534 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2535 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2536 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2537 case EL_BELT4_SWITCH_L: return GFX_BELT4_SWITCH_L;
2538 case EL_BELT4_SWITCH_M: return GFX_BELT4_SWITCH_M;
2539 case EL_BELT4_SWITCH_R: return GFX_BELT4_SWITCH_R;
2540 case EL_LANDMINE: return GFX_LANDMINE;
2541 case EL_ENVELOPE: return GFX_ENVELOPE;
2542 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2543 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2544 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2545 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2546 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2547 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2548 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2549 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2550 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2551 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2552 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2553 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2554 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2555 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2556 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2557 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2558 case EL_MOLE_UP: return GFX_MOLE_UP;
2559 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2560 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2561 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2562 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2563 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2564 case EL_DX_UNKNOWN_229: return GFX_DX_UNKNOWN_229;
2565 case EL_DX_UNKNOWN_233: return GFX_DX_UNKNOWN_233;
2569 if (IS_CHAR(element))
2570 return GFX_CHAR_START + (element - EL_CHAR_START);
2571 else if (element >= EL_SP_START && element <= EL_SP_END)
2573 int nr_element = element - EL_SP_START;
2574 int gfx_per_line = 8;
2576 (nr_element / gfx_per_line) * SP_PER_LINE +
2577 (nr_element % gfx_per_line);
2579 return GFX_START_ROCKSSP + nr_graphic;