rnd-19981026-1
[rocksndiamonds.git] / src / screens.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  screens.c                                               *
12 ***********************************************************/
13
14 #include "screens.h"
15 #include "events.h"
16 #include "sound.h"
17 #include "game.h"
18 #include "tools.h"
19 #include "editor.h"
20 #include "misc.h"
21 #include "files.h"
22 #include "buttons.h"
23 #include "tape.h"
24 #include "joystick.h"
25 #include "cartoons.h"
26 #include "network.h"
27
28 #ifdef MSDOS
29 extern unsigned char get_ascii(KeySym);
30 #endif
31
32 void DrawHeadline()
33 {
34   int x1 = SX+(SXSIZE - strlen(GAMETITLE_STRING) * FONT1_XSIZE) / 2;
35   int y1 = SY+8;
36   int x2 = SX+(SXSIZE - strlen(COPYRIGHT_STRING) * FONT2_XSIZE) / 2;
37   int y2 = SY+46;
38
39   DrawText(x1,y1, GAMETITLE_STRING, FS_BIG, FC_YELLOW);
40   DrawText(x2,y2, COPYRIGHT_STRING, FS_SMALL, FC_RED);
41 }
42
43 void DrawMainMenu()
44 {
45   int i;
46
47   FadeSounds();
48   GetPlayerConfig();
49   LoadLevel(level_nr);
50
51   ClearWindow();
52   DrawHeadline();
53   DrawText(SX + 32,    SY + 2*32, "Name:", FS_BIG, FC_GREEN);
54   DrawText(SX + 6*32,  SY + 2*32, local_player->alias_name, FS_BIG, FC_RED);
55   DrawText(SX + 32,    SY + 3*32, "Level:", FS_BIG, FC_GREEN);
56   DrawText(SX + 11*32, SY + 3*32, int2str(level_nr,3), FS_BIG,
57            (level_nr<leveldir[leveldir_nr].levels ? FC_RED : FC_YELLOW));
58   DrawText(SX + 32,    SY + 4*32, "Hall Of Fame", FS_BIG, FC_GREEN);
59   DrawText(SX + 32,    SY + 5*32, "Level Creator", FS_BIG, FC_GREEN);
60   DrawText(SY + 32,    SY + 6*32, "Info Screen", FS_BIG, FC_GREEN);
61   DrawText(SX + 32,    SY + 7*32, "Start Game", FS_BIG, FC_GREEN);
62   DrawText(SX + 32,    SY + 8*32, "Setup", FS_BIG, FC_GREEN);
63   DrawText(SX + 32,    SY + 9*32, "Quit", FS_BIG, FC_GREEN);
64
65   DrawMicroLevel(MICROLEV_XPOS,MICROLEV_YPOS);
66
67   for(i=2;i<10;i++)
68     DrawGraphic(0,i,GFX_KUGEL_BLAU);
69   DrawGraphic(10,3,GFX_PFEIL_L);
70   DrawGraphic(14,3,GFX_PFEIL_R);
71
72   DrawText(SX+40+16,SY+326,"A Game by Artsoft Entertainment",FS_SMALL,FC_BLUE);
73   DrawText(SX+40+16,SY+344,"Graphics: Deluxe Paint IV Amiga",
74            FS_SMALL,FC_BLUE);
75   DrawText(SX+60+16,SY+362,"Sounds: AudioMaster IV Amiga",
76            FS_SMALL,FC_BLUE);
77
78   FadeToFront();
79   InitAnimation();
80   HandleMainMenu(0,0,0,0,MB_MENU_INITIALIZE);
81
82   TapeStop();
83   if (TAPE_IS_EMPTY(tape))
84     LoadLevelTape(level_nr);
85   DrawCompleteVideoDisplay();
86
87   OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2);
88
89   ClearEventQueue();
90   XAutoRepeatOn(display);
91 }
92
93 void HandleMainMenu(int mx, int my, int dx, int dy, int button)
94 {
95   static int choice = 3;
96   static int redraw = TRUE;
97   int x = (mx+32-SX)/32, y = (my+32-SY)/32;
98
99   if (redraw || button == MB_MENU_INITIALIZE)
100   {
101     DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
102     redraw = FALSE;
103   }
104
105   if (button == MB_MENU_INITIALIZE)
106     return;
107
108   if (dx || dy)
109   {
110     if (dx && choice==4)
111     {
112       x = (dx<0 ? 11 : 15);
113       y = 4;
114     }
115     else if (dy)
116     {
117       x = 1;
118       y = choice+dy;
119     }
120     else
121       x = y = 0;
122
123     if (y<3)
124       y = 3;
125     else if (y>10)
126       y = 10;
127   }
128
129   if (!mx && !my && !dx && !dy)
130   {
131     x = 1;
132     y = choice;
133   }
134
135   if (y==4 && ((x==11 && level_nr>0) ||
136                (x==15 && level_nr<leveldir[leveldir_nr].levels-1)) &&
137       button)
138   {
139     static long level_delay = 0;
140     int step = (button==1 ? 1 : button==2 ? 5 : 10);
141     int new_level_nr, old_level_nr = level_nr;
142
143     new_level_nr = level_nr + (x==11 ? -step : +step);
144     if (new_level_nr<0)
145       new_level_nr = 0;
146     if (new_level_nr>leveldir[leveldir_nr].levels-1)
147       new_level_nr = leveldir[leveldir_nr].levels-1;
148
149     if (old_level_nr==new_level_nr || !DelayReached(&level_delay,150))
150       goto out;
151
152     level_nr = new_level_nr;
153
154
155     /*
156     if (level_nr > local_player->handicap)
157       level_nr = local_player->handicap;
158     */
159
160
161     DrawTextExt(drawto,gc,SX+11*32,SY+3*32,
162                 int2str(level_nr,3), FS_BIG,FC_RED);
163     DrawTextExt(window,gc,SX+11*32,SY+3*32,
164                 int2str(level_nr,3), FS_BIG,FC_RED);
165
166     LoadLevel(level_nr);
167     DrawMicroLevel(MICROLEV_XPOS,MICROLEV_YPOS);
168
169     TapeErase();
170     LoadLevelTape(level_nr);
171     DrawCompleteVideoDisplay();
172
173     /* needed because DrawMicroLevel() takes some time */
174     BackToFront();
175     XSync(display,FALSE);
176     DelayReached(&level_delay,0);       /* reset delay counter */
177   }
178   else if (x==1 && y>=3 && y<=10)
179   {
180     if (button)
181     {
182       if (y!=choice)
183       {
184         DrawGraphic(0,y-1,GFX_KUGEL_ROT);
185         DrawGraphic(0,choice-1,GFX_KUGEL_BLAU);
186       }
187       choice = y;
188     }
189     else
190     {
191       if (y==3)
192       {
193         game_status = TYPENAME;
194         HandleTypeName(strlen(local_player->alias_name),0);
195       }
196       else if (y==4)
197       {
198         if (num_leveldirs)
199         {
200           game_status = CHOOSELEVEL;
201
202
203           SaveLevelSetup();
204
205 #if 0
206           SavePlayerInfo(PLAYER_LEVEL);
207 #endif
208
209
210           DrawChooseLevel();
211         }
212       }
213       else if (y==5)
214       {
215         game_status = HALLOFFAME;
216         DrawHallOfFame(-1);
217       }
218       else if (y==6)
219       {
220         game_status = LEVELED;
221         if (leveldir[leveldir_nr].readonly)
222           Request("This level is read only !",REQ_CONFIRM);
223         DrawLevelEd();
224       }
225       else if (y==7)
226       {
227         game_status = HELPSCREEN;
228         DrawHelpScreen();
229       }
230       else if (y==8)
231       {
232         if (setup.autorecord_on)
233           TapeStartRecording();
234
235         if (options.network)
236           SendToServer_StartPlaying();
237         else
238         {
239           game_status = PLAYING;
240           InitGame();
241         }
242       }
243       else if (y==9)
244       {
245         game_status = SETUP;
246         DrawSetupScreen();
247       }
248       else if (y==10)
249       {
250
251         SaveLevelSetup();
252
253 #if 0
254         SavePlayerInfo(PLAYER_LEVEL);
255 #endif
256
257         if (Request("Do you really want to quit ?", REQ_ASK | REQ_STAY_CLOSED))
258           game_status = EXITGAME;
259       }
260
261       if (!button)
262         redraw = TRUE;
263     }
264   }
265   BackToFront();
266
267   out:
268
269   if (game_status==MAINMENU)
270     DoAnimation();
271 }
272
273 #define MAX_HELPSCREEN_ELS      10
274 #define HA_NEXT                 -999
275 #define HA_END                  -1000
276
277 static long helpscreen_state;
278 static int helpscreen_step[MAX_HELPSCREEN_ELS];
279 static int helpscreen_frame[MAX_HELPSCREEN_ELS];
280 static int helpscreen_delay[MAX_HELPSCREEN_ELS];
281 static int helpscreen_action[] =
282 {
283   GFX_SPIELER1_DOWN,4,2,
284   GFX_SPIELER1_UP,4,2,
285   GFX_SPIELER1_LEFT,4,2,
286   GFX_SPIELER1_RIGHT,4,2,
287   GFX_SPIELER1_PUSH_LEFT,4,2,
288   GFX_SPIELER1_PUSH_RIGHT,4,2,                                  HA_NEXT,
289   GFX_ERDREICH,1,100,                                           HA_NEXT,
290   GFX_LEERRAUM,1,100,                                           HA_NEXT,
291   GFX_MORAST_LEER,1,100,                                        HA_NEXT,
292   GFX_BETON,1,100,                                              HA_NEXT,
293   GFX_MAUERWERK,1,100,                                          HA_NEXT,
294   GFX_MAUER_R1,3,4, GFX_MAUERWERK,1,20, GFX_LEERRAUM,1,10,
295   GFX_MAUER_L1,3,4, GFX_MAUERWERK,1,20, GFX_LEERRAUM,1,10,      HA_NEXT,
296   GFX_UNSICHTBAR,1,100,                                         HA_NEXT,
297   GFX_FELSBODEN,1,100,                                          HA_NEXT,
298   GFX_CHAR_A,30,4, GFX_CHAR_AUSRUF,32,4,                        HA_NEXT,
299   GFX_EDELSTEIN,2,5,                                            HA_NEXT,
300   GFX_DIAMANT,2,5,                                              HA_NEXT,
301   GFX_EDELSTEIN_BD,2,5,                                         HA_NEXT,
302   GFX_EDELSTEIN_GELB,2,5, GFX_EDELSTEIN_ROT,2,5,
303   GFX_EDELSTEIN_LILA,2,5,                                       HA_NEXT,
304   GFX_FELSBROCKEN,4,5,                                          HA_NEXT,
305   GFX_BOMBE,1,50, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10,         HA_NEXT,
306   GFX_KOKOSNUSS,1,50, GFX_CRACKINGNUT,3,1, GFX_EDELSTEIN,1,10,  HA_NEXT,
307   GFX_ERZ_EDEL,1,50, GFX_EXPLOSION,8,1, GFX_EDELSTEIN,1,10,     HA_NEXT,
308   GFX_ERZ_DIAM,1,50, GFX_EXPLOSION,8,1, GFX_DIAMANT,1,10,       HA_NEXT,
309   GFX_ERZ_EDEL_BD,1,50, GFX_EXPLOSION,8,1,GFX_EDELSTEIN_BD,1,10,HA_NEXT,
310   GFX_ERZ_EDEL_GELB,1,50, GFX_EXPLOSION,8,1,
311   GFX_EDELSTEIN_GELB,1,10, GFX_ERZ_EDEL_ROT,1,50,
312   GFX_EXPLOSION,8,1, GFX_EDELSTEIN_ROT,1,10,
313   GFX_ERZ_EDEL_LILA,1,50, GFX_EXPLOSION,8,1,
314   GFX_EDELSTEIN_LILA,1,10,                                      HA_NEXT,
315   GFX_GEBLUBBER,4,4,                                            HA_NEXT,
316   GFX_SCHLUESSEL1,4,25,                                         HA_NEXT,
317   GFX_PFORTE1,4,25,                                             HA_NEXT,
318   GFX_PFORTE1X,4,25,                                            HA_NEXT,
319   GFX_DYNAMIT_AUS,1,100,                                        HA_NEXT,
320   GFX_DYNAMIT,7,6, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10,        HA_NEXT,
321   GFX_DYNABOMB+0,4,3, GFX_DYNABOMB+3,1,3, GFX_DYNABOMB+2,1,3,
322   GFX_DYNABOMB+1,1,3, GFX_DYNABOMB+0,1,3, GFX_EXPLOSION,8,1,
323   GFX_LEERRAUM,1,10,                                            HA_NEXT,
324   GFX_DYNABOMB_NR,1,100,                                        HA_NEXT,
325   GFX_DYNABOMB_SZ,1,100,                                        HA_NEXT,
326   GFX_FLIEGER+4,1,3, GFX_FLIEGER+0,1,3, GFX_FLIEGER+4,1,3,
327   GFX_FLIEGER+5,1,3, GFX_FLIEGER+1,1,3, GFX_FLIEGER+5,1,3,
328   GFX_FLIEGER+6,1,3, GFX_FLIEGER+2,1,3, GFX_FLIEGER+6,1,3,
329   GFX_FLIEGER+7,1,3, GFX_FLIEGER+3,1,3, GFX_FLIEGER+7,1,3,      HA_NEXT,
330   GFX_KAEFER+4,1,1, GFX_KAEFER+0,1,1, GFX_KAEFER+4,1,1,
331   GFX_KAEFER+5,1,1, GFX_KAEFER+1,1,1, GFX_KAEFER+5,1,1,
332   GFX_KAEFER+6,1,1, GFX_KAEFER+2,1,1, GFX_KAEFER+6,1,1,
333   GFX_KAEFER+7,1,1, GFX_KAEFER+3,1,1, GFX_KAEFER+7,1,1,         HA_NEXT,
334   GFX_BUTTERFLY,2,2,                                            HA_NEXT,
335   GFX_FIREFLY,2,2,                                              HA_NEXT,
336   GFX_PACMAN+0,1,3, GFX_PACMAN+4,1,2, GFX_PACMAN+0,1,3,
337   GFX_PACMAN+1,1,3, GFX_PACMAN+5,1,2, GFX_PACMAN+1,1,3,
338   GFX_PACMAN+2,1,3, GFX_PACMAN+6,1,2, GFX_PACMAN+2,1,3,
339   GFX_PACMAN+3,1,3, GFX_PACMAN+7,1,2, GFX_PACMAN+3,1,3,         HA_NEXT,
340   GFX_MAMPFER+0,4,1, GFX_MAMPFER+3,1,1, GFX_MAMPFER+2,1,1,
341   GFX_MAMPFER+1,1,1, GFX_MAMPFER+0,1,1,                         HA_NEXT,
342   GFX_MAMPFER2+0,4,1, GFX_MAMPFER2+3,1,1, GFX_MAMPFER2+2,1,1,
343   GFX_MAMPFER2+1,1,1, GFX_MAMPFER2+0,1,1,                       HA_NEXT,
344   GFX_ROBOT+0,4,1, GFX_ROBOT+3,1,1, GFX_ROBOT+2,1,1,
345   GFX_ROBOT+1,1,1, GFX_ROBOT+0,1,1,                             HA_NEXT,
346   GFX_MAULWURF_DOWN,4,2,
347   GFX_MAULWURF_UP,4,2,
348   GFX_MAULWURF_LEFT,4,2,
349   GFX_MAULWURF_RIGHT,4,2,                                       HA_NEXT,
350   GFX_PINGUIN_DOWN,4,2,
351   GFX_PINGUIN_UP,4,2,
352   GFX_PINGUIN_LEFT,4,2,
353   GFX_PINGUIN_RIGHT,4,2,                                        HA_NEXT,
354   GFX_SCHWEIN_DOWN,4,2,
355   GFX_SCHWEIN_UP,4,2,
356   GFX_SCHWEIN_LEFT,4,2,
357   GFX_SCHWEIN_RIGHT,4,2,                                        HA_NEXT,
358   GFX_DRACHE_DOWN,4,2,
359   GFX_DRACHE_UP,4,2,
360   GFX_DRACHE_LEFT,4,2,
361   GFX_DRACHE_RIGHT,4,2,                                         HA_NEXT,
362   GFX_SONDE_START,8,1,                                          HA_NEXT,
363   GFX_ABLENK,4,1,                                               HA_NEXT,
364   GFX_BIRNE_AUS,1,25, GFX_BIRNE_EIN,1,25,                       HA_NEXT,
365   GFX_ZEIT_VOLL,1,25, GFX_ZEIT_LEER,1,25,                       HA_NEXT,
366   GFX_TROPFEN,1,25, GFX_AMOEBING,4,1, GFX_AMOEBE_LEBT,1,10,     HA_NEXT,
367   GFX_AMOEBE_TOT+2,2,50, GFX_AMOEBE_TOT,2,50,                   HA_NEXT,
368   GFX_AMOEBE_LEBT,4,40,                                         HA_NEXT,
369   GFX_AMOEBE_LEBT,1,10, GFX_AMOEBING,4,2,                       HA_NEXT,
370   GFX_AMOEBE_LEBT,1,25, GFX_AMOEBE_TOT,1,25, GFX_EXPLOSION,8,1,
371   GFX_DIAMANT,1,10,                                             HA_NEXT,
372   GFX_LIFE,1,100,                                               HA_NEXT,
373   GFX_LIFE_ASYNC,1,100,                                         HA_NEXT,
374   GFX_SIEB_LEER,4,2,                                            HA_NEXT,
375   GFX_SIEB2_LEER,4,2,                                           HA_NEXT,
376   GFX_AUSGANG_ZU,1,100, GFX_AUSGANG_ACT,4,2,
377   GFX_AUSGANG_AUF+0,4,2, GFX_AUSGANG_AUF+3,1,2,
378   GFX_AUSGANG_AUF+2,1,2, GFX_AUSGANG_AUF+1,1,2,                 HA_NEXT,
379   GFX_AUSGANG_AUF+0,4,2, GFX_AUSGANG_AUF+3,1,2,
380   GFX_AUSGANG_AUF+2,1,2, GFX_AUSGANG_AUF+1,1,2,                 HA_NEXT,
381   HA_END
382 };
383 static char *helpscreen_eltext[][2] =
384 {
385  {"THE HERO:",                          "(Is _this_ guy good old Rockford?)"},
386  {"Normal sand:",                       "You can dig through it"},
387  {"Empty field:",                       "You can walk through it"},
388  {"Quicksand: You cannot pass it,",     "but rocks can fall though it"},
389  {"Massive Wall:",                      "Nothing can go through it"},
390  {"Normal Wall: You can't go through",  "it, but you can bomb it away"},
391  {"Growing Wall: Grows to the left or", "right if there is an empty field"},
392  {"Invisible Wall: Behaves like normal","wall, but is invisible"},
393  {"Old Wall: Like normal wall, but",    "some things can fall down from it"},
394  {"Letter Wall: Looks like a letter,",  "behaves like a normal wall"},
395  {"Emerald: You must collect enough of","them to finish a level"},
396  {"Diamond: Counts as 3 emeralds, but", "can be destroyed by rocks"},
397  {"Diamond (BD style): Counts like one","emerald and behaves a bit different"},
398  {"Colorful Gems:",                     "Seem to behave like Emeralds"},
399  {"Rock: Smashes several things;",      "Can be moved by the player"},
400  {"Bomb: You can move it, but be",      "careful when dropping it"},
401  {"Nut: Throw a rock on it to open it;","Each nut contains an emerald"},
402  {"Wall with an emerald inside:",       "Bomb the wall away to get it"},
403  {"Wall with a diamond inside:",        "Bomb the wall away to get it"},
404  {"Wall with BD style diamond inside:", "Bomb the wall away to get it"},
405  {"Wall with colorful gem inside:",     "Bomb the wall away to get it"},
406  {"Acid: Things that fall in are gone", "forever (including our hero)"},
407  {"Key: Opens the door that has the",   "same color (red/yellow/green/blue)"},
408  {"Door: Can be opened by the key",     "with the same color"},
409  {"Door: You have to find out the",     "right color of the key for it"},
410  {"Dynamite: Collect it and use it to", "destroy walls or kill enemies"},
411  {"Dynamite: This one explodes after",  "a few seconds"},
412  {"Dyna Bomb: Explodes in 4 directions","with variable explosion size"},
413  {"Dyna Bomb: Increases the number of", "dyna bombs available at a time"},
414  {"Dyna Bomb: Increases the size of",   "explosion of dyna bombs"},
415  {"Spaceship: Moves at the left side",  "of walls; don't touch it!"},
416  {"Bug: Moves at the right side",       "of walls; don't touch it!"},
417  {"Butterfly: Moves at the right side", "of walls; don't touch it!"},
418  {"Firefly: Moves at the left side",    "of walls; don't touch it!"},
419  {"Pacman: Eats the amoeba and you,",   "if you're not careful"},
420  {"Cruncher: Eats diamonds and you,",   "if you're not careful"},
421  {"Cruncher (BD style):",               "Eats almost everything"},
422  {"Robot: Tries to kill the player",    ""},
423  {"The mole: You must guide him savely","to the exit; he will follow you"},
424  {"The penguin: Guide him to the exit,","but keep him away from monsters!"},
425  {"The Pig: Harmless, but eats all",    "gems it can get"},
426  {"The Dragon: Breathes fire,",         "especially to some monsters"},
427  {"Sonde: Follows you everywhere;",     "harmless, but may block your way"},
428  {"Magic Wheel: Touch it to get rid of","the robots for some seconds"},
429  {"Light Bulb: All of them must be",    "switched on to finish a level"},
430  {"Extra Time Orb: Adds some seconds",  "to the time available for the level"},
431  {"Amoeba Drop: Grows to an amoeba on", "the ground - don't touch it"},
432  {"Dead Amoeba: Does not grow, but",    "can still kill bugs and spaceships"},
433  {"Normal Amoeba: Grows through empty", "fields, sand and quicksand"},
434  {"Dropping Amoeba: This one makes",    "drops that grow to a new amoeba"},
435  {"Living Amoeba (BD style): Contains", "other element, when surrounded"},
436  {"Game Of Life: Behaves like the well","known 'Game Of Life' (2333 style)"},
437  {"Biomaze: A bit like the 'Game Of",   "Life', but builds crazy mazes"},
438  {"Magic Wall: Changes rocks, emeralds","and diamonds when they pass it"},
439  {"Magic Wall (BD style):",             "Changes rocks and BD style diamonds"},
440  {"Exit door: Opens if you have enough","emeralds to finish the level"},
441  {"Open exit door: Enter here to leave","the level and exit the actual game"},
442 };
443 static int num_helpscreen_els = sizeof(helpscreen_eltext)/(2*sizeof(char *));
444
445 static char *helpscreen_music[][3] =
446 {
447   { "Alchemy",                  "Ian Boddy",            "Drive" },
448   { "The Chase",                "Propaganda",           "A Secret Wish" },
449   { "Network 23",               "Tangerine Dream",      "Exit" },
450   { "Czardasz",                 "Robert Pieculewicz",   "Czardasz" },
451   { "21st Century Common Man",  "Tangerine Dream",      "Tyger" },
452   { "Voyager",                  "The Alan Parsons Project","Pyramid" },
453   { "Twilight Painter",         "Tangerine Dream",      "Heartbreakers" }
454 };
455 static int helpscreen_musicpos;
456
457 void DrawHelpScreenElAction(int start)
458 {
459   int i = 0, j = 0;
460   int frame, graphic;
461   int xstart = SX+16, ystart = SY+64+2*32, ystep = TILEY+4;
462
463   while(helpscreen_action[j] != HA_END)
464   {
465     if (i>=start+MAX_HELPSCREEN_ELS || i>=num_helpscreen_els)
466       break;
467     else if (i<start || helpscreen_delay[i-start])
468     {
469       if (i>=start && helpscreen_delay[i-start])
470         helpscreen_delay[i-start]--;
471
472       while(helpscreen_action[j] != HA_NEXT)
473         j++;
474       j++;
475       i++;
476       continue;
477     }
478
479     j += 3*helpscreen_step[i-start];
480     graphic = helpscreen_action[j++];
481
482     if (helpscreen_frame[i-start])
483     {
484       frame = helpscreen_action[j++] - helpscreen_frame[i-start];
485       helpscreen_frame[i-start]--;
486     }
487     else
488     {
489       frame = 0;
490       helpscreen_frame[i-start] = helpscreen_action[j++]-1;
491     }
492
493     helpscreen_delay[i-start] = helpscreen_action[j++] - 1;
494
495     if (helpscreen_action[j] == HA_NEXT)
496     {
497       if (!helpscreen_frame[i-start])
498         helpscreen_step[i-start] = 0;
499     }
500     else
501     {
502       if (!helpscreen_frame[i-start])
503         helpscreen_step[i-start]++;
504       while(helpscreen_action[j] != HA_NEXT)
505         j++;
506     }
507     j++;
508
509     DrawGraphicExt(drawto, gc, xstart, ystart+(i-start)*ystep, graphic+frame);
510     i++;
511   }
512
513   for(i=2;i<16;i++)
514   {
515     MarkTileDirty(0,i);
516     MarkTileDirty(1,i);
517   }
518 }
519
520 void DrawHelpScreenElText(int start)
521 {
522   int i;
523   int xstart = SX+56, ystart = SY+65+2*32, ystep = TILEY+4;
524   char text[FULL_SXSIZE/FONT2_XSIZE+10];
525
526   ClearWindow();
527   DrawHeadline();
528
529   sprintf(text,"The game elements:");
530   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
531            text,FS_SMALL,FC_GREEN);
532
533   for(i=start;i<start+MAX_HELPSCREEN_ELS && i<num_helpscreen_els;i++)
534   {
535     DrawText(xstart,ystart+(i-start)*ystep+(*helpscreen_eltext[i][1] ? 0 : 8),
536              helpscreen_eltext[i][0],FS_SMALL,FC_YELLOW);
537     DrawText(xstart,ystart+(i-start)*ystep+16,
538              helpscreen_eltext[i][1],FS_SMALL,FC_YELLOW);
539   }
540
541   sprintf(text,"Press any key or button for next page");
542   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+SYSIZE-20,
543            text,FS_SMALL,FC_BLUE);
544 }
545
546 void DrawHelpScreenMusicText(int num)
547 {
548   int ystart = 150, ystep = 30;
549   char text[FULL_SXSIZE/FONT2_XSIZE+10];
550
551   FadeSounds();
552   ClearWindow();
553   DrawHeadline();
554
555   sprintf(text,"The game background music loops:");
556   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
557            text,FS_SMALL,FC_GREEN);
558
559   sprintf(text,"Excerpt from");
560   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+0*ystep,
561            text,FS_SMALL,FC_YELLOW);
562   sprintf(text,"%c%s%c",'\"',helpscreen_music[num][0],'\"');
563   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+1*ystep,
564            text,FS_SMALL,FC_RED);
565   sprintf(text,"by");
566   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+2*ystep,
567            text,FS_SMALL,FC_YELLOW);
568   sprintf(text,"%s",helpscreen_music[num][1]);
569   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+3*ystep,
570            text,FS_SMALL,FC_RED);
571   sprintf(text,"from the album");
572   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+4*ystep,
573            text,FS_SMALL,FC_YELLOW);
574   sprintf(text,"%c%s%c",'\"',helpscreen_music[num][2],'\"');
575   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+5*ystep,
576            text,FS_SMALL,FC_RED);
577
578   sprintf(text,"Press any key or button for next page");
579   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+SYSIZE-20,
580            text,FS_SMALL,FC_BLUE);
581
582   PlaySoundLoop(background_loop[num]);
583 }
584
585 void DrawHelpScreenCreditsText()
586 {
587   int ystart = 150, ystep = 30;
588   char text[FULL_SXSIZE/FONT2_XSIZE+10];
589
590   FadeSounds();
591   ClearWindow();
592   DrawHeadline();
593
594   sprintf(text,"Program information:");
595   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
596            text,FS_SMALL,FC_GREEN);
597
598   sprintf(text,"This game is Freeware!");
599   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+0*ystep,
600            text,FS_SMALL,FC_YELLOW);
601   sprintf(text,"If you like it, send e-mail to:");
602   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+1*ystep,
603            text,FS_SMALL,FC_YELLOW);
604   sprintf(text,"aeglos@valinor.owl.de");
605   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+2*ystep,
606            text,FS_SMALL,FC_RED);
607   sprintf(text,"or SnailMail to:");
608   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+3*ystep,
609            text,FS_SMALL,FC_YELLOW);
610   sprintf(text,"Holger Schemel");
611   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+4*ystep,
612            text,FS_SMALL,FC_RED);
613   sprintf(text,"Sennehof 28");
614   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+4*ystep+20,
615            text,FS_SMALL,FC_RED);
616   sprintf(text,"33659 Bielefeld");
617   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+4*ystep+40,
618            text,FS_SMALL,FC_RED);
619   sprintf(text,"Germany");
620   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+4*ystep+60,
621            text,FS_SMALL,FC_RED);
622
623   sprintf(text,"If you have created new levels,");
624   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+7*ystep,
625            text,FS_SMALL,FC_YELLOW);
626   sprintf(text,"send them to me to include them!");
627   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+8*ystep,
628            text,FS_SMALL,FC_YELLOW);
629   sprintf(text,":-)");
630   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+9*ystep,
631            text,FS_SMALL,FC_YELLOW);
632
633   sprintf(text,"Press any key or button for main menu");
634   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+SYSIZE-20,
635            text,FS_SMALL,FC_BLUE);
636 }
637
638 void DrawHelpScreen()
639 {
640   int i;
641
642   CloseDoor(DOOR_CLOSE_2);
643
644   for(i=0;i<MAX_HELPSCREEN_ELS;i++)
645     helpscreen_step[i] = helpscreen_frame[i] = helpscreen_delay[i] = 0;
646   helpscreen_musicpos = 0;
647   helpscreen_state = 0;
648   DrawHelpScreenElText(0);
649   DrawHelpScreenElAction(0);
650
651   FadeToFront();
652   InitAnimation();
653   PlaySoundLoop(SND_RHYTHMLOOP);
654 }
655
656 void HandleHelpScreen(int button)
657 {
658   static long hs_delay = 0;
659   int num_helpscreen_els_pages =
660     (num_helpscreen_els + MAX_HELPSCREEN_ELS-1) / MAX_HELPSCREEN_ELS;
661   int button_released = !button;
662   int i;
663
664   if (button_released)
665   {
666     if (helpscreen_state<num_helpscreen_els_pages-1)
667     {
668       for(i=0;i<MAX_HELPSCREEN_ELS;i++)
669         helpscreen_step[i] = helpscreen_frame[i] = helpscreen_delay[i] = 0;
670       helpscreen_state++;
671       DrawHelpScreenElText(helpscreen_state*MAX_HELPSCREEN_ELS);
672       DrawHelpScreenElAction(helpscreen_state*MAX_HELPSCREEN_ELS);
673     }
674     else if (helpscreen_state<num_helpscreen_els_pages+num_bg_loops-1)
675     {
676       helpscreen_state++;
677       DrawHelpScreenMusicText(helpscreen_state-num_helpscreen_els_pages);
678     }
679     else if (helpscreen_state==num_helpscreen_els_pages+num_bg_loops-1)
680     {
681       helpscreen_state++;
682       DrawHelpScreenCreditsText();
683     }
684     else
685     {
686       FadeSounds();
687       DrawMainMenu();
688       game_status = MAINMENU;
689     }
690   }
691   else
692   {
693     if (DelayReached(&hs_delay,GAME_FRAME_DELAY * 2))
694     {
695       if (helpscreen_state<num_helpscreen_els_pages)
696         DrawHelpScreenElAction(helpscreen_state*MAX_HELPSCREEN_ELS);
697     }
698     DoAnimation();
699   }
700
701   BackToFront();
702 }
703
704
705 #if 0
706 void CheckCheat()
707 {
708   int old_handicap = local_player->handicap;
709
710   if (!strcmp(local_player->alias_name,"Artsoft"))
711     local_player->handicap = leveldir[leveldir_nr].levels-1;
712
713   if (local_player->handicap != old_handicap)
714   {
715     SavePlayerInfo(PLAYER_LEVEL);
716     level_nr = local_player->handicap;
717   }
718 }
719 #endif
720
721
722 void HandleTypeName(int newxpos, KeySym key)
723 {
724   static int xpos = 0, ypos = 2;
725   unsigned char ascii;
726
727   if (newxpos)
728   {
729     xpos = newxpos;
730     DrawText(SX+6*32, SY+ypos*32, local_player->alias_name, FS_BIG, FC_YELLOW);
731     DrawGraphic(xpos+6,ypos,GFX_KUGEL_ROT);
732     return;
733   }
734
735 #ifndef MSDOS
736   if ((key>=XK_A && key<=XK_Z) || (key>=XK_a && key<=XK_z && 
737       xpos<MAX_NAMELEN-1))
738   {
739     if (key>=XK_A && key<=XK_Z)
740       ascii = 'A'+(char)(key-XK_A);
741     if (key>=XK_a && key<=XK_z)
742       ascii = 'a'+(char)(key-XK_a);
743 #else
744   if((ascii = get_ascii(key)) && xpos<MAX_NAMELEN-1)
745   {
746 #endif
747     local_player->alias_name[xpos] = ascii;
748     local_player->alias_name[xpos+1] = 0;
749     xpos++;
750     DrawTextExt(drawto,gc,SX+6*32,SY+ypos*32,
751                 local_player->alias_name,FS_BIG,FC_YELLOW);
752     DrawTextExt(window,gc,SX+6*32,SY+ypos*32,
753                 local_player->alias_name,FS_BIG,FC_YELLOW);
754     DrawGraphic(xpos+6,ypos,GFX_KUGEL_ROT);
755   }
756   else if ((key==XK_Delete || key==XK_BackSpace) && xpos>0)
757   {
758     xpos--;
759     local_player->alias_name[xpos] = 0;
760     DrawGraphic(xpos+6,ypos,GFX_KUGEL_ROT);
761     DrawGraphic(xpos+7,ypos,GFX_LEERRAUM);
762   }
763   else if (key==XK_Return && xpos>0)
764   {
765     DrawText(SX+6*32,SY+ypos*32,local_player->alias_name,FS_BIG,FC_RED);
766     DrawGraphic(xpos+6,ypos,GFX_LEERRAUM);
767
768
769     SaveSetup();
770
771
772 #if 0
773     SavePlayerInfo(PLAYER_SETUP);
774 #endif
775
776
777
778 #if 0
779     CheckCheat();
780 #endif
781
782
783     game_status = MAINMENU;
784 /*
785     DrawMainMenu();
786 */
787
788   }
789   BackToFront();
790 }
791
792 void DrawChooseLevel()
793 {
794   int i;
795
796   CloseDoor(DOOR_CLOSE_2);
797
798   ClearWindow();
799   DrawText(SX,SY,"Level Directories",FS_BIG,FC_GREEN);
800   for(i=0;i<num_leveldirs;i++)
801   {
802     DrawText(SX+32,SY+(i+2)*32,leveldir[i].name,FS_BIG,FC_YELLOW);
803     DrawGraphic(0,i+2,GFX_KUGEL_BLAU);
804   }
805
806   FadeToFront();
807   InitAnimation();
808   HandleChooseLevel(0,0,0,0,MB_MENU_INITIALIZE);
809 }
810
811 void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
812 {
813   static int choice = 3;
814   static int redraw = TRUE;
815   int x = (mx+32-SX)/32, y = (my+32-SY)/32;
816
817   if (button == MB_MENU_INITIALIZE)
818   {
819     redraw = TRUE;
820     choice = leveldir_nr + 3;
821   }
822
823   if (redraw)
824   {
825     DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
826     redraw = FALSE;
827   }
828
829   if (button == MB_MENU_INITIALIZE)
830     return;
831
832   if (dx || dy)
833   {
834     if (dy)
835     {
836       x = 1;
837       y = choice+dy;
838     }
839     else
840       x = y = 0;
841
842     if (y<3)
843       y = 3;
844     else if (y>num_leveldirs+2)
845       y = num_leveldirs+2;
846   }
847
848   if (!mx && !my && !dx && !dy)
849   {
850     x = 1;
851     y = choice;
852   }
853
854   if (x==1 && y>=3 && y<=num_leveldirs+2)
855   {
856     if (button)
857     {
858       if (y!=choice)
859       {
860         DrawGraphic(0,y-1,GFX_KUGEL_ROT);
861         DrawGraphic(0,choice-1,GFX_KUGEL_BLAU);
862       }
863       choice = y;
864     }
865     else
866     {
867       local_player->leveldir_nr = leveldir_nr = y-3;
868
869       SaveLevelSetup();
870
871       /*
872       LoadPlayerInfo(PLAYER_LEVEL);
873       SavePlayerInfo(PLAYER_SETUP);
874       */
875
876
877 #if 0
878       CheckCheat();
879 #endif
880
881
882       TapeErase();
883       LoadLevelTape(level_nr);
884
885       game_status = MAINMENU;
886       DrawMainMenu();
887       redraw = TRUE;
888     }
889   }
890   BackToFront();
891
892   if (game_status==CHOOSELEVEL)
893     DoAnimation();
894 }
895
896 void DrawHallOfFame(int pos)
897 {
898   int y;
899   char txt[40];
900
901   CloseDoor(DOOR_CLOSE_2);
902
903   if (pos<0) 
904     LoadScore(level_nr);
905   ClearWindow();
906   DrawText(SX+64,SY+10,"Hall Of Fame",FS_BIG,FC_YELLOW);
907   sprintf(txt,"HighScores of Level %d",level_nr);
908   DrawText(SX+256-strlen(txt)*7,SY+48,txt,FS_SMALL,FC_RED);
909   for(y=0;y<MAX_SCORE_ENTRIES;y++)
910   {
911     DrawText(SX,SY+64+y*32,".................",FS_BIG,
912              (y==pos ? FC_RED : FC_GREEN));
913     DrawText(SX,SY+64+y*32,highscore[y].Name,FS_BIG,
914              (y==pos ? FC_RED : FC_GREEN));
915     DrawText(SX+12*32,SY+64+y*32,
916              int2str(highscore[y].Score,5),FS_BIG,
917              (y==pos ? FC_RED : FC_GREEN));
918   }
919
920   FadeToFront();
921   InitAnimation();
922   PlaySound(SND_HALLOFFAME);
923 }
924
925 void HandleHallOfFame(int button)
926 {
927   int button_released = !button;
928
929   if (button_released)
930   {
931     FadeSound(SND_HALLOFFAME);
932     game_status = MAINMENU;
933     DrawMainMenu();
934     BackToFront();
935   }
936   else
937     DoAnimation();
938 }
939
940 void DrawSetupScreen()
941 {
942   int i;
943
944
945 #if 0
946   static struct setup
947   {
948     unsigned int bit;
949     char *text, *mode[2];
950     int color[2];
951   } setup[] =
952   {
953     {SETUP_SOUND,       "Sound:",       {"on", "off"},  {FC_YELLOW,FC_BLUE}},
954     {SETUP_SOUND_LOOPS, " Sound Loops:",{"on", "off"},  {FC_YELLOW,FC_BLUE}},
955     {SETUP_SOUND_MUSIC, " Game Music:", {"on", "off"},  {FC_YELLOW,FC_BLUE}},
956     {SETUP_TOONS,       "Toons:",       {"on", "off"},  {FC_YELLOW,FC_BLUE}},
957     {SETUP_DIRECT_DRAW, "Buffered gfx:",{"off","on" },  {FC_BLUE,FC_YELLOW}},
958     {SETUP_SCROLL_DELAY,"Scroll Delay:",{"on", "off"},  {FC_YELLOW,FC_BLUE}},
959     {SETUP_SOFT_SCROLL, "Soft Scroll.:",{"on", "off"},  {FC_YELLOW,FC_BLUE}},
960     {SETUP_FADING,      "Fading:",      {"on", "off"},  {FC_YELLOW,FC_BLUE}},
961     {SETUP_QUICK_DOORS, "Quick Doors:", {"on", "off"},  {FC_YELLOW,FC_BLUE}},
962     {SETUP_AUTO_RECORD, "Auto-Record:", {"on", "off"},  {FC_YELLOW,FC_BLUE}},
963     {0,                 "Input Devices",{"",   ""},     {0,0}},
964     {0,                 "",             {"",   ""},     {0,0}},
965     {0,                 "",             {"",   ""},     {0,0}},
966     {0,                 "Exit",         {"",   ""},     {0,0}},
967     {0,                 "Save and exit",{"",   ""},     {0,0}}
968   };
969 #endif
970
971   static struct setup
972   {
973     boolean *value;
974     char *text, *mode[2];
975     int color[2];
976   } setup_info[] =
977   {
978     { &setup.sound_on,  "Sound:",       {"on", "off"},{FC_YELLOW,FC_BLUE}},
979     { &setup.sound_loops_on," Sound Loops:",{"on", "off"},{FC_YELLOW,FC_BLUE}},
980     { &setup.sound_music_on," Game Music:", {"on", "off"},{FC_YELLOW,FC_BLUE}},
981     { &setup.toons_on,  "Toons:",       {"on", "off"},{FC_YELLOW,FC_BLUE}},
982     { &setup.direct_draw_on,"Buffered gfx:",{"off","on" },{FC_BLUE,FC_YELLOW}},
983     { &setup.scroll_delay_on,"Scroll Delay:",{"on", "off"},{FC_YELLOW,FC_BLUE}},
984     { &setup.soft_scrolling_on, "Soft Scroll.:",{"on", "off"},{FC_YELLOW,FC_BLUE}},
985     { &setup.fading_on, "Fading:",      {"on", "off"},{FC_YELLOW,FC_BLUE}},
986     { &setup.quick_doors,"Quick Doors:",        {"on", "off"},{FC_YELLOW,FC_BLUE}},
987     { &setup.autorecord_on,"Auto-Record:",      {"on", "off"},{FC_YELLOW,FC_BLUE}},
988     { NULL,             "Input Devices",{"",   ""},     {0,0}},
989     { NULL,             "",             {"",   ""},     {0,0}},
990     { NULL,             "",             {"",   ""},     {0,0}},
991     { NULL,             "Exit",         {"",   ""},     {0,0}},
992     { NULL,             "Save and exit",{"",   ""},     {0,0}}
993   };
994
995   CloseDoor(DOOR_CLOSE_2);
996   ClearWindow();
997   DrawText(SX+16, SY+16, "SETUP",FS_BIG,FC_YELLOW);
998
999
1000   /*
1001   printf("setup.sound_loops_on == %d\n", setup.sound_loops_on);
1002   */
1003
1004
1005   for(i=SETUP_SCREEN_POS_START;i<=SETUP_SCREEN_POS_END;i++)
1006   {
1007     int base = i - SETUP_SCREEN_POS_START;
1008
1009     if (!(i >= SETUP_SCREEN_POS_EMPTY1 && i <= SETUP_SCREEN_POS_EMPTY2))
1010     {
1011       DrawGraphic(0,i,GFX_KUGEL_BLAU);
1012       DrawText(SX+32,SY+i*32, setup_info[base].text, FS_BIG,FC_GREEN);
1013     }
1014
1015 #if 0
1016     if (i < SETUP_SCREEN_POS_EMPTY1)
1017     {
1018       int setting_bit = setup_info[base].bit;
1019       int setting_pos = ((local_player->setup & setting_bit) != 0 ? 0 : 1);
1020     }
1021 #endif
1022
1023     if (setup_info[base].value)
1024     {
1025       int setting_value = *setup_info[base].value;
1026       int setting_pos = (setting_value != 0 ? 0 : 1);
1027
1028       DrawText(SX+14*32, SY+i*32,setup_info[base].mode[setting_pos],
1029                FS_BIG,setup_info[base].color[setting_pos]);
1030     }
1031   }
1032
1033   FadeToFront();
1034   InitAnimation();
1035   HandleSetupScreen(0,0,0,0,MB_MENU_INITIALIZE);
1036 }
1037
1038 void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
1039 {
1040   static int choice = 3;
1041   static int redraw = TRUE;
1042   int x = (mx+32-SX)/32, y = (my+32-SY)/32;
1043   int pos_start  = SETUP_SCREEN_POS_START  + 1;
1044   int pos_empty1 = SETUP_SCREEN_POS_EMPTY1 + 1;
1045   int pos_empty2 = SETUP_SCREEN_POS_EMPTY2 + 1;
1046   int pos_end    = SETUP_SCREEN_POS_END    + 1;
1047
1048   if (button == MB_MENU_INITIALIZE)
1049     redraw = TRUE;
1050
1051   if (redraw)
1052   {
1053     DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
1054     redraw = FALSE;
1055   }
1056
1057   if (button == MB_MENU_INITIALIZE)
1058     return;
1059
1060   if (dx || dy)
1061   {
1062     if (dy)
1063     {
1064       x = 1;
1065       y = choice+dy;
1066     }
1067     else
1068       x = y = 0;
1069
1070     if (y >= pos_empty1 && y <= pos_empty2)
1071       y = (dy > 0 ? pos_empty2 + 1 : pos_empty1 - 1);
1072
1073     if (y < pos_start)
1074       y = pos_start;
1075     else if (y > pos_end)
1076       y = pos_end;
1077   }
1078
1079   if (!mx && !my && !dx && !dy)
1080   {
1081     x = 1;
1082     y = choice;
1083   }
1084
1085   if (x==1 && y >= pos_start && y <= pos_end &&
1086       !(y >= pos_empty1 && y <= pos_empty2))
1087   {
1088     if (button)
1089     {
1090       if (y!=choice)
1091       {
1092         DrawGraphic(0,y-1,GFX_KUGEL_ROT);
1093         DrawGraphic(0,choice-1,GFX_KUGEL_BLAU);
1094       }
1095       choice = y;
1096     }
1097     else
1098     {
1099       int yy = y-1;
1100
1101       if (y==3 && sound_status==SOUND_AVAILABLE)
1102       {
1103         if (setup.sound_on)
1104         {
1105           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1106           DrawText(SX+14*32, SY+(yy+1)*32,"off",FS_BIG,FC_BLUE);
1107           DrawText(SX+14*32, SY+(yy+2)*32,"off",FS_BIG,FC_BLUE);
1108           setup.sound_loops_on = FALSE;
1109           setup.sound_music_on = FALSE;
1110         }
1111         else
1112           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1113         setup.sound_on = !setup.sound_on;
1114       }
1115       else if (y==4 && sound_loops_allowed)
1116       {
1117         if (setup.sound_loops_on)
1118           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1119         else
1120         {
1121           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1122           DrawText(SX+14*32, SY+(yy-1)*32,"on ",FS_BIG,FC_YELLOW);
1123           setup.sound_on = TRUE;
1124         }
1125         setup.sound_loops_on = !setup.sound_loops_on;
1126       }
1127       else if (y==5 && sound_loops_allowed)
1128       {
1129         if (setup.sound_music_on)
1130           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1131         else
1132         {
1133           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1134           DrawText(SX+14*32, SY+(yy-2)*32,"on ",FS_BIG,FC_YELLOW);
1135           setup.sound_on = TRUE;
1136         }
1137         setup.sound_music_on = !setup.sound_music_on;
1138       }
1139       else if (y==6)
1140       {
1141         if (setup.toons_on)
1142           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1143         else
1144           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1145         setup.toons_on = !setup.toons_on;
1146       }
1147       else if (y==7)
1148       {
1149         if (!setup.direct_draw_on)
1150           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1151         else
1152           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1153         setup.direct_draw_on = !setup.direct_draw_on;
1154       }
1155       else if (y==8)
1156       {
1157         if (setup.scroll_delay_on)
1158           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1159         else
1160           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1161         setup.scroll_delay_on = !setup.scroll_delay_on;
1162       }
1163       else if (y==9)
1164       {
1165         if (setup.soft_scrolling_on)
1166           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1167         else
1168           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1169         setup.soft_scrolling_on = !setup.soft_scrolling_on;
1170       }
1171       else if (y==10)
1172       {
1173         if (setup.fading_on)
1174           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1175         else
1176           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1177         setup.fading_on = !setup.fading_on;
1178       }
1179       else if (y==11)
1180       {
1181         if (setup.quick_doors)
1182           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1183         else
1184           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1185         setup.quick_doors = !setup.quick_doors;
1186       }
1187       else if (y==12)
1188       {
1189         if (setup.autorecord_on)
1190           DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
1191         else
1192           DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
1193         setup.autorecord_on = !setup.autorecord_on;
1194       }
1195       else if (y==13)
1196       {
1197         game_status = SETUPINPUT;
1198         DrawSetupInputScreen();
1199         redraw = TRUE;
1200       }
1201       else if (y==pos_end-1 || y==pos_end)
1202       {
1203         if (y==pos_end)
1204         {
1205
1206
1207           SaveSetup();
1208
1209
1210 #if 0
1211           SavePlayerInfo(PLAYER_SETUP);
1212 #endif
1213
1214           SaveJoystickData();
1215         }
1216
1217         game_status = MAINMENU;
1218         DrawMainMenu();
1219         redraw = TRUE;
1220       }
1221     }
1222   }
1223   BackToFront();
1224
1225   if (game_status==SETUP)
1226     DoAnimation();
1227 }
1228
1229 void DrawSetupInputScreen()
1230 {
1231   ClearWindow();
1232   DrawText(SX+16, SY+16, "SETUP INPUT", FS_BIG, FC_YELLOW);
1233
1234   DrawGraphic(0, 2, GFX_KUGEL_BLAU);
1235   DrawGraphic(0, 3, GFX_KUGEL_BLAU);
1236   DrawGraphic(0, 4, GFX_KUGEL_BLAU);
1237   DrawGraphic(0, 15, GFX_KUGEL_BLAU);
1238   DrawGraphic(10, 2, GFX_PFEIL_L);
1239   DrawGraphic(12, 2, GFX_PFEIL_R);
1240
1241   DrawText(SX+32, SY+2*32, "Player:", FS_BIG, FC_GREEN);
1242   DrawText(SX+32, SY+3*32, "Device:", FS_BIG, FC_GREEN);
1243   DrawText(SX+32, SY+15*32, "Exit", FS_BIG, FC_GREEN);
1244
1245   FadeToFront();
1246   InitAnimation();
1247   HandleSetupInputScreen(0,0,0,0,MB_MENU_INITIALIZE);
1248 }
1249
1250 static void drawPlayerSetupInputInfo(int player_nr)
1251 {
1252   int i;
1253   static struct SetupKeyboardInfo custom_key;
1254   static struct
1255   {
1256     KeySym *keysym;
1257     char *text;
1258   } custom[] =
1259   {
1260     { &custom_key.left,  "Joystick Left"  },
1261     { &custom_key.right, "Joystick Right" },
1262     { &custom_key.up,    "Joystick Up"    },
1263     { &custom_key.down,  "Joystick Down"  },
1264     { &custom_key.snap,  "Button 1"       },
1265     { &custom_key.bomb,  "Button 2"       }
1266   };
1267
1268   custom_key = setup.input[player_nr].key;
1269
1270   DrawText(SX+11*32, SY+2*32, int2str(player_nr + 1, 1), FS_BIG, FC_RED);
1271   DrawGraphic(8, 2, GFX_SPIELER1 + player_nr);
1272
1273   if (setup.input[player_nr].use_joystick)
1274   {
1275     DrawText(SX+8*32, SY+3*32,
1276              (setup.input[player_nr].joystick_nr == 0 ?
1277               "Joystick1" : "Joystick2"),
1278              FS_BIG, FC_YELLOW);
1279     DrawText(SX+32, SY+4*32, "Calibrate", FS_BIG, FC_GREEN);
1280   }
1281   else
1282   {
1283     DrawText(SX+8*32, SY+3*32, "Keyboard ", FS_BIG, FC_YELLOW);
1284     DrawText(SX+32, SY+4*32, "Customize", FS_BIG, FC_GREEN);
1285   }
1286
1287   DrawText(SX+32, SY+5*32, "Actual Settings:", FS_BIG, FC_GREEN);
1288   DrawGraphic(1, 6, GFX_PFEIL_L);
1289   DrawGraphic(1, 7, GFX_PFEIL_R);
1290   DrawGraphic(1, 8, GFX_PFEIL_O);
1291   DrawGraphic(1, 9, GFX_PFEIL_U);
1292   DrawText(SX+2*32, SY+6*32, ":", FS_BIG, FC_BLUE);
1293   DrawText(SX+2*32, SY+7*32, ":", FS_BIG, FC_BLUE);
1294   DrawText(SX+2*32, SY+8*32, ":", FS_BIG, FC_BLUE);
1295   DrawText(SX+2*32, SY+9*32, ":", FS_BIG, FC_BLUE);
1296   DrawText(SX+32, SY+10*32, "Snap Field:", FS_BIG, FC_BLUE);
1297   DrawText(SX+32, SY+12*32, "Place Bomb:", FS_BIG, FC_BLUE);
1298
1299   for (i=0; i<6; i++)
1300   {
1301     int ypos = 6 + i + (i > 3 ? i-3 : 0);
1302
1303     DrawText(SX + 3*32, SY + ypos*32,
1304              "              ", FS_BIG, FC_YELLOW);
1305     DrawText(SX + 3*32, SY + ypos*32,
1306              (setup.input[player_nr].use_joystick ?
1307               custom[i].text :
1308               getKeyNameFromKeySym(*custom[i].keysym)),
1309              FS_BIG, FC_YELLOW);
1310   }
1311 }
1312
1313 void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
1314 {
1315   static int choice = 3;
1316   static int player_nr = 0;
1317   static int redraw = TRUE;
1318   int x = (mx+32-SX)/32, y = (my+32-SY)/32;
1319   int pos_start  = SETUPINPUT_SCREEN_POS_START  + 1;
1320   int pos_empty1 = SETUPINPUT_SCREEN_POS_EMPTY1 + 1;
1321   int pos_empty2 = SETUPINPUT_SCREEN_POS_EMPTY2 + 1;
1322   int pos_end    = SETUPINPUT_SCREEN_POS_END    + 1;
1323
1324   if (button == MB_MENU_INITIALIZE)
1325   {
1326     drawPlayerSetupInputInfo(player_nr);
1327     redraw = TRUE;
1328   }
1329
1330   if (redraw)
1331   {
1332     DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
1333     redraw = FALSE;
1334   }
1335
1336   if (button == MB_MENU_INITIALIZE)
1337     return;
1338
1339   if (dx || dy)
1340   {
1341     if (dx && choice == 3)
1342     {
1343       x = (dx < 0 ? 11 : 13);
1344       y = 3;
1345     }
1346     else if (dx && choice == 4)
1347     {
1348       button = MB_MENU_CHOICE;
1349       x = 1;
1350       y = 4;
1351     }
1352     else if (dy)
1353     {
1354       x = 1;
1355       y = choice + dy;
1356     }
1357     else
1358       x = y = 0;
1359
1360     if (y >= pos_empty1 && y <= pos_empty2)
1361       y = (dy > 0 ? pos_empty2 + 1 : pos_empty1 - 1);
1362
1363     if (y < pos_start)
1364       y = pos_start;
1365     else if (y > pos_end)
1366       y = pos_end;
1367   }
1368
1369   if (!mx && !my && !dx && !dy)
1370   {
1371     x = 1;
1372     y = choice;
1373   }
1374
1375   if (y == 3 && ((x == 1 && !button) || ((x == 11 || x == 13) && button)))
1376   {
1377     static long delay = 0;
1378
1379     if (!DelayReached(&delay,150))
1380       goto out;
1381
1382     player_nr = (player_nr + (x == 11 ? -1 : +1) + MAX_PLAYERS) % MAX_PLAYERS;
1383
1384     drawPlayerSetupInputInfo(player_nr);
1385   }
1386   else if (x==1 && y >= pos_start && y <= pos_end &&
1387            !(y >= pos_empty1 && y <= pos_empty2))
1388   {
1389     if (button)
1390     {
1391       if (y != choice)
1392       {
1393         DrawGraphic(0, y-1, GFX_KUGEL_ROT);
1394         DrawGraphic(0, choice-1, GFX_KUGEL_BLAU);
1395       }
1396       choice = y;
1397     }
1398     else
1399     {
1400       if (y == 4)
1401       {
1402         int one_joystick_nr       = (dx >= 0 ? 0 : 1);
1403         int the_other_joystick_nr = (dx >= 0 ? 1 : 0);
1404
1405         if (setup.input[player_nr].use_joystick)
1406         {
1407           if (setup.input[player_nr].joystick_nr == one_joystick_nr)
1408             setup.input[player_nr].joystick_nr = the_other_joystick_nr;
1409           else
1410             setup.input[player_nr].use_joystick = FALSE;
1411         }
1412         else
1413         {
1414           setup.input[player_nr].use_joystick = TRUE;
1415           setup.input[player_nr].joystick_nr = one_joystick_nr;
1416         }
1417
1418         drawPlayerSetupInputInfo(player_nr);
1419       }
1420       else if (y == 5)
1421       {
1422         if (setup.input[player_nr].use_joystick)
1423           CalibrateJoystick(setup.input[player_nr].joystick_nr);
1424         else
1425           CustomizeKeyboard(player_nr);
1426
1427         redraw = TRUE;
1428       }
1429       else if (y == pos_end)
1430       {
1431         game_status = SETUP;
1432         DrawSetupScreen();
1433         redraw = TRUE;
1434       }
1435     }
1436   }
1437   BackToFront();
1438
1439   out:
1440
1441   if (game_status == SETUPINPUT)
1442     DoAnimation();
1443 }
1444
1445 void CustomizeKeyboard(int player_nr)
1446 {
1447   int i;
1448   int step_nr;
1449   boolean finished = FALSE;
1450   static struct SetupKeyboardInfo custom_key;
1451   static struct
1452   {
1453     KeySym *keysym;
1454     char *text;
1455   } customize_step[] =
1456   {
1457     { &custom_key.left,  "Move Left"  },
1458     { &custom_key.right, "Move Right" },
1459     { &custom_key.up,    "Move Up"    },
1460     { &custom_key.down,  "Move Down"  },
1461     { &custom_key.snap,  "Snap Field" },
1462     { &custom_key.bomb,  "Place Bomb" }
1463   };
1464
1465   /* read existing key bindings from player setup */
1466   custom_key = setup.input[player_nr].key;
1467
1468   ClearWindow();
1469   DrawText(SX + 16, SY + 16, "Keyboard Input", FS_BIG, FC_YELLOW);
1470
1471   BackToFront();
1472   InitAnimation();
1473
1474   step_nr = 0;
1475   DrawText(SX, SY + (2+2*step_nr)*32,
1476            customize_step[step_nr].text, FS_BIG, FC_RED);
1477   DrawText(SX, SY + (2+2*step_nr+1)*32,
1478            "Key:", FS_BIG, FC_RED);
1479   DrawText(SX + 4*32, SY + (2+2*step_nr+1)*32,
1480            getKeyNameFromKeySym(*customize_step[step_nr].keysym),
1481            FS_BIG, FC_BLUE);
1482
1483   while(!finished)
1484   {
1485     if (XPending(display))      /* got event from X server */
1486     {
1487       XEvent event;
1488
1489       XNextEvent(display, &event);
1490
1491       switch(event.type)
1492       {
1493         case KeyPress:
1494           {
1495             KeySym key = XLookupKeysym((XKeyEvent *)&event,
1496                                        ((XKeyEvent *)&event)->state);
1497
1498             if (key == XK_Escape || (key == XK_Return && step_nr == 6))
1499             {
1500               finished = TRUE;
1501               break;
1502             }
1503
1504             /* press 'Enter' to keep the existing key binding */
1505             if (key == XK_Return || step_nr == 6)
1506               key = *customize_step[step_nr].keysym;
1507
1508             /* check if key already used */
1509             for (i=0; i<step_nr; i++)
1510               if (*customize_step[i].keysym == key)
1511                 break;
1512             if (i < step_nr)
1513               break;
1514
1515             /* got new key binding */
1516             *customize_step[step_nr].keysym = key;
1517             DrawText(SX + 4*32, SY + (2+2*step_nr+1)*32,
1518                      "             ", FS_BIG, FC_YELLOW);
1519             DrawText(SX + 4*32, SY + (2+2*step_nr+1)*32,
1520                      getKeyNameFromKeySym(key), FS_BIG, FC_YELLOW);
1521             step_nr++;
1522
1523             /* un-highlight last query */
1524             DrawText(SX, SY+(2+2*(step_nr-1))*32,
1525                      customize_step[step_nr-1].text, FS_BIG, FC_GREEN);
1526             DrawText(SX, SY+(2+2*(step_nr-1)+1)*32,
1527                      "Key:", FS_BIG, FC_GREEN);
1528
1529             /* press 'Enter' to leave */
1530             if (step_nr == 6)
1531             {
1532               DrawText(SX + 16, SY + 15*32+16,
1533                        "Press Enter", FS_BIG, FC_YELLOW);
1534               break;
1535             }
1536
1537             /* query next key binding */
1538             DrawText(SX, SY+(2+2*step_nr)*32,
1539                      customize_step[step_nr].text, FS_BIG, FC_RED);
1540             DrawText(SX, SY+(2+2*step_nr+1)*32,
1541                      "Key:", FS_BIG, FC_RED);
1542             DrawText(SX + 4*32, SY+(2+2*step_nr+1)*32,
1543                      getKeyNameFromKeySym(*customize_step[step_nr].keysym),
1544                      FS_BIG, FC_BLUE);
1545           }
1546           break;
1547
1548         case KeyRelease:
1549           key_joystick_mapping = 0;
1550           break;
1551
1552         default:
1553           HandleOtherEvents(&event);
1554           break;
1555       }
1556     }
1557
1558     BackToFront();
1559     DoAnimation();
1560
1561     /* don't eat all CPU time */
1562     Delay(10);
1563   }
1564
1565   /* write new key bindings back to player setup */
1566   setup.input[player_nr].key = custom_key;
1567
1568   StopAnimation();
1569   DrawSetupInputScreen();
1570 }
1571
1572 void CalibrateJoystick(int joystick_nr)
1573 {
1574 #ifdef __FreeBSD__
1575   struct joystick joy_ctrl;
1576 #else
1577   struct joystick_control
1578   {
1579     int buttons;
1580     int x;
1581     int y;
1582   } joy_ctrl;
1583 #endif
1584
1585 #ifdef MSDOS
1586   char joy_nr[4];
1587 #endif
1588
1589   int new_joystick_xleft = 128, new_joystick_xright = 128;
1590   int new_joystick_yupper = 128, new_joystick_ylower = 128;
1591   int new_joystick_xmiddle, new_joystick_ymiddle;
1592   int x, y, last_x, last_y, xpos = 8, ypos = 3;
1593   boolean check[3][3];
1594   int check_remaining = 3 * 3;
1595   int joy;
1596   int result = -1;
1597
1598   if (joystick_status == JOYSTICK_OFF)
1599     return;
1600
1601   ClearWindow();
1602   DrawText(SX,      SY +  6*32, " ROTATE JOYSTICK ",FS_BIG,FC_YELLOW);
1603   DrawText(SX,      SY +  7*32, "IN ALL DIRECTIONS",FS_BIG,FC_YELLOW);
1604   DrawText(SX + 16, SY +  9*32, "  IF ALL BALLS  ",FS_BIG,FC_YELLOW);
1605   DrawText(SX,      SY + 10*32, "   ARE YELLOW,   ",FS_BIG,FC_YELLOW);
1606   DrawText(SX,      SY + 11*32, "  PRESS BUTTON!  ",FS_BIG,FC_YELLOW);
1607
1608   for(y=0; y<3; y++)
1609   {
1610     for(x=0; x<3; x++)
1611     {
1612       check[x][y] = FALSE;
1613       DrawGraphic(xpos + x - 1, ypos + y - 1, GFX_KUGEL_BLAU);
1614     }
1615   }
1616
1617   joy = Joystick();
1618   last_x = (joy & JOY_LEFT ? -1 : joy & JOY_RIGHT ? +1 : 0);
1619   last_y = (joy & JOY_UP   ? -1 : joy & JOY_DOWN  ? +1 : 0);
1620   DrawGraphic(xpos + last_x, ypos + last_y, GFX_KUGEL_ROT);
1621
1622   BackToFront();
1623
1624 #ifdef __FreeBSD__
1625   joy_ctrl.b1 = joy_ctrl.b2 = 0;
1626 #else
1627   joy_ctrl.buttons = 0;
1628 #endif
1629
1630   while(Joystick() & JOY_BUTTON);
1631
1632   InitAnimation();
1633
1634   while(result < 0)
1635   {
1636     if (XPending(display))      /* got event from X server */
1637     {
1638       XEvent event;
1639
1640       XNextEvent(display, &event);
1641
1642       switch(event.type)
1643       {
1644         case KeyPress:
1645           switch(XLookupKeysym((XKeyEvent *)&event,
1646                                ((XKeyEvent *)&event)->state))
1647           {
1648             case XK_Return:
1649               if (check_remaining == 0)
1650                 result = 1;
1651               break;
1652
1653             case XK_Escape:
1654               result = 0;
1655               break;
1656
1657             default:
1658               break;
1659           }
1660           break;
1661
1662         case KeyRelease:
1663           key_joystick_mapping = 0;
1664           break;
1665
1666         default:
1667           HandleOtherEvents(&event);
1668           break;
1669       }
1670     }
1671
1672     if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
1673     {
1674       joystick_status = JOYSTICK_OFF;
1675       goto error_out;
1676     }
1677
1678     new_joystick_xleft  = MIN(new_joystick_xleft,  joy_ctrl.x);
1679     new_joystick_xright = MAX(new_joystick_xright, joy_ctrl.x);
1680     new_joystick_yupper = MIN(new_joystick_yupper, joy_ctrl.y);
1681     new_joystick_ylower = MAX(new_joystick_ylower, joy_ctrl.y);
1682
1683     new_joystick_xmiddle =
1684       new_joystick_xleft + (new_joystick_xright - new_joystick_xleft) / 2;
1685     new_joystick_ymiddle =
1686       new_joystick_yupper + (new_joystick_ylower - new_joystick_yupper) / 2;
1687
1688     joystick[joystick_nr].xleft = new_joystick_xleft;
1689     joystick[joystick_nr].yupper = new_joystick_yupper;
1690     joystick[joystick_nr].xright = new_joystick_xright;
1691     joystick[joystick_nr].ylower = new_joystick_ylower;
1692     joystick[joystick_nr].xmiddle = new_joystick_xmiddle;
1693     joystick[joystick_nr].ymiddle = new_joystick_ymiddle;
1694
1695     CheckJoystickData();
1696
1697     joy = Joystick();
1698
1699     if (joy & JOY_BUTTON && check_remaining == 0)
1700       result = 1;
1701
1702     x = (joy & JOY_LEFT ? -1 : joy & JOY_RIGHT ? +1 : 0);
1703     y = (joy & JOY_UP   ? -1 : joy & JOY_DOWN  ? +1 : 0);
1704
1705     if (x != last_x || y != last_y)
1706     {
1707       DrawGraphic(xpos + last_x, ypos + last_y, GFX_KUGEL_GELB);
1708       DrawGraphic(xpos + x,      ypos + y,      GFX_KUGEL_ROT);
1709
1710       last_x = x;
1711       last_y = y;
1712
1713       if (check_remaining > 0 && !check[x+1][y+1])
1714       {
1715         check[x+1][y+1] = TRUE;
1716         check_remaining--;
1717       }
1718
1719 #if 0
1720       printf("LEFT / MIDDLE / RIGHT == %d / %d / %d\n",
1721              joystick[joystick_nr].xleft,
1722              joystick[joystick_nr].xmiddle,
1723              joystick[joystick_nr].xright);
1724       printf("UP / MIDDLE / DOWN == %d / %d / %d\n",
1725              joystick[joystick_nr].yupper,
1726              joystick[joystick_nr].ymiddle,
1727              joystick[joystick_nr].ylower);
1728 #endif
1729     }
1730
1731     BackToFront();
1732     DoAnimation();
1733
1734     /* don't eat all CPU time */
1735     Delay(10);
1736   }
1737
1738   StopAnimation();
1739
1740   DrawSetupInputScreen();
1741   while(Joystick() & JOY_BUTTON);
1742   return;
1743
1744   error_out:
1745
1746   ClearWindow();
1747   DrawText(SX+16, SY+16, "NO JOYSTICK",FS_BIG,FC_YELLOW);
1748   DrawText(SX+16, SY+48, " AVAILABLE ",FS_BIG,FC_YELLOW);
1749   BackToFront();
1750   Delay(3000);
1751   DrawSetupInputScreen();
1752 }
1753
1754 void CalibrateJoystick_OLD()
1755 {
1756 #ifdef __FreeBSD__
1757   struct joystick joy_ctrl;
1758 #else
1759   struct joystick_control
1760   {
1761     int buttons;
1762     int x;
1763     int y;
1764   } joy_ctrl;
1765 #endif
1766
1767 #ifdef MSDOS
1768   char joy_nr[4];
1769 #endif
1770
1771   int joystick_nr = setup.input[0].joystick_nr;
1772   int new_joystick_xleft, new_joystick_xright, new_joystick_xmiddle;
1773   int new_joystick_yupper, new_joystick_ylower, new_joystick_ymiddle;
1774
1775   if (joystick_status == JOYSTICK_OFF)
1776     goto error_out;
1777
1778 #ifndef MSDOS
1779   ClearWindow();
1780   DrawText(SX+16, SY+7*32, "MOVE JOYSTICK TO",FS_BIG,FC_YELLOW);
1781   DrawText(SX+16, SY+8*32, " THE UPPER LEFT ",FS_BIG,FC_YELLOW);
1782   DrawText(SX+16, SY+9*32, "AND PRESS BUTTON",FS_BIG,FC_YELLOW);
1783   BackToFront();
1784
1785 #ifdef __FreeBSD__
1786   joy_ctrl.b1 = joy_ctrl.b2 = 0;
1787 #else
1788   joy_ctrl.buttons = 0;
1789 #endif
1790   while(Joystick() & JOY_BUTTON);
1791 #ifdef __FreeBSD__
1792   while(!(joy_ctrl.b1 || joy_ctrl.b2))
1793 #else
1794   while(!joy_ctrl.buttons)
1795 #endif
1796   {
1797     if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
1798     {
1799       joystick_status=JOYSTICK_OFF;
1800       goto error_out;
1801     }
1802     Delay(10);
1803   }
1804
1805   new_joystick_xleft = joy_ctrl.x;
1806   new_joystick_yupper = joy_ctrl.y;
1807
1808   ClearWindow();
1809   DrawText(SX+16, SY+7*32, "MOVE JOYSTICK TO",FS_BIG,FC_YELLOW);
1810   DrawText(SX+32, SY+8*32, "THE LOWER RIGHT",FS_BIG,FC_YELLOW);
1811   DrawText(SX+16, SY+9*32, "AND PRESS BUTTON",FS_BIG,FC_YELLOW);
1812   BackToFront();
1813
1814 #ifdef __FreeBSD__
1815   joy_ctrl.b1 = joy_ctrl.b2 = 0;
1816 #else
1817   joy_ctrl.buttons = 0;
1818 #endif
1819   while(Joystick() & JOY_BUTTON);
1820 #ifdef __FreeBSD__
1821   while(!(joy_ctrl.b1 || joy_ctrl.b2))
1822 #else
1823   while(!joy_ctrl.buttons)
1824 #endif
1825   {
1826     if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
1827     {
1828       joystick_status=JOYSTICK_OFF;
1829       goto error_out;
1830     }
1831     Delay(10);
1832   }
1833
1834   new_joystick_xright = joy_ctrl.x;
1835   new_joystick_ylower = joy_ctrl.y;
1836
1837   ClearWindow();
1838   DrawText(SX+32, SY+16+7*32, "CENTER JOYSTICK",FS_BIG,FC_YELLOW);
1839   DrawText(SX+16, SY+16+8*32, "AND PRESS BUTTON",FS_BIG,FC_YELLOW);
1840   BackToFront();
1841
1842 #ifdef __FreeBSD__
1843   joy_ctrl.b1 = joy_ctrl.b2 = 0;
1844 #else
1845   joy_ctrl.buttons = 0;
1846 #endif
1847   while(Joystick() & JOY_BUTTON);
1848 #ifdef __FreeBSD__
1849   while(!(joy_ctrl.b1 || joy_ctrl.b2))
1850 #else
1851   while(!joy_ctrl.buttons)
1852 #endif
1853   {
1854     if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
1855     {
1856       joystick_status=JOYSTICK_OFF;
1857       goto error_out;
1858     }
1859     Delay(10);
1860   }
1861
1862   new_joystick_xmiddle = joy_ctrl.x;
1863   new_joystick_ymiddle = joy_ctrl.y;
1864
1865   joystick[joystick_nr].xleft = new_joystick_xleft;
1866   joystick[joystick_nr].yupper = new_joystick_yupper;
1867   joystick[joystick_nr].xright = new_joystick_xright;
1868   joystick[joystick_nr].ylower = new_joystick_ylower;
1869   joystick[joystick_nr].xmiddle = new_joystick_xmiddle;
1870   joystick[joystick_nr].ymiddle = new_joystick_ymiddle;
1871
1872   CheckJoystickData();
1873
1874   DrawSetupScreen();
1875   while(Joystick() & JOY_BUTTON);
1876   return;
1877
1878 #endif
1879   error_out:
1880
1881 #ifdef MSDOS
1882   joy_nr[0] = '#';
1883   joy_nr[1] = SETUP_2ND_JOYSTICK_ON(local_player->setup)+49;
1884   joy_nr[2] = '\0';
1885
1886   remove_joystick();
1887   ClearWindow();
1888   DrawText(SX+32, SY+7*32, "CENTER JOYSTICK",FS_BIG,FC_YELLOW);
1889   DrawText(SX+16+7*32, SY+8*32, joy_nr, FS_BIG,FC_YELLOW);
1890   DrawText(SX+32, SY+9*32, "AND PRESS A KEY",FS_BIG,FC_YELLOW);
1891   BackToFront();
1892
1893   for(clear_keybuf();!keypressed(););
1894   install_joystick(JOY_TYPE_2PADS);
1895
1896   ClearWindow();
1897   DrawText(SX+16, SY+7*32, "MOVE JOYSTICK TO",FS_BIG,FC_YELLOW);
1898   DrawText(SX+16, SY+8*32, " THE UPPER LEFT ",FS_BIG,FC_YELLOW);
1899   DrawText(SX+32, SY+9*32, "AND PRESS A KEY",FS_BIG,FC_YELLOW);
1900   BackToFront();
1901
1902   for(clear_keybuf();!keypressed(););
1903   calibrate_joystick(SETUP_2ND_JOYSTICK_ON(local_player->setup));
1904
1905   ClearWindow();
1906   DrawText(SX+16, SY+7*32, "MOVE JOYSTICK TO",FS_BIG,FC_YELLOW);
1907   DrawText(SX+32, SY+8*32, "THE LOWER RIGHT",FS_BIG,FC_YELLOW);
1908   DrawText(SX+32, SY+9*32, "AND PRESS A KEY",FS_BIG,FC_YELLOW);
1909   BackToFront();
1910
1911   for(clear_keybuf();!keypressed(););
1912   calibrate_joystick(SETUP_2ND_JOYSTICK_ON(local_player->setup));
1913
1914   DrawSetupScreen();
1915   return;
1916 #endif
1917
1918   ClearWindow();
1919   DrawText(SX+16, SY+16, "NO JOYSTICK",FS_BIG,FC_YELLOW);
1920   DrawText(SX+16, SY+48, " AVAILABLE ",FS_BIG,FC_YELLOW);
1921   BackToFront();
1922   Delay(3000);
1923   DrawSetupScreen();
1924 }
1925
1926 void HandleGameActions()
1927 {
1928   if (game_status != PLAYING)
1929     return;
1930
1931   if (local_player->LevelSolved)
1932     GameWon();
1933
1934   if (AllPlayersGone && !TAPE_IS_STOPPED(tape))
1935     TapeStop();
1936
1937   GameActions();
1938
1939   BackToFront();
1940 }
1941
1942 void HandleVideoButtons(int mx, int my, int button)
1943 {
1944   if (game_status != MAINMENU && game_status != PLAYING)
1945     return;
1946
1947   switch(CheckVideoButtons(mx,my,button))
1948   {
1949     case BUTTON_VIDEO_EJECT:
1950       TapeStop();
1951       if (TAPE_IS_EMPTY(tape))
1952       {
1953         LoadLevelTape(level_nr);
1954         if (TAPE_IS_EMPTY(tape))
1955           Request("No tape for this level !",REQ_CONFIRM);
1956       }
1957       else
1958       {
1959         if (tape.changed)
1960           SaveLevelTape(tape.level_nr);
1961         TapeErase();
1962       }
1963       DrawCompleteVideoDisplay();
1964       break;
1965
1966     case BUTTON_VIDEO_STOP:
1967       TapeStop();
1968       break;
1969
1970     case BUTTON_VIDEO_PAUSE:
1971       TapeTogglePause();
1972       break;
1973
1974     case BUTTON_VIDEO_REC:
1975       if (TAPE_IS_STOPPED(tape))
1976       {
1977         TapeStartRecording();
1978
1979         if (options.network)
1980           SendToServer_StartPlaying();
1981         else
1982         {
1983           game_status = PLAYING;
1984           InitGame();
1985         }
1986       }
1987       else if (tape.pausing)
1988       {
1989         if (tape.playing)       /* PLAYING -> PAUSING -> RECORDING */
1990         {
1991           tape.pos[tape.counter].delay = tape.delay_played;
1992           tape.playing = FALSE;
1993           tape.recording = TRUE;
1994           tape.changed = TRUE;
1995
1996           DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON,0);
1997         }
1998         else
1999           TapeTogglePause();
2000       }
2001       break;
2002
2003     case BUTTON_VIDEO_PLAY:
2004       if (TAPE_IS_EMPTY(tape))
2005         break;
2006
2007       if (TAPE_IS_STOPPED(tape))
2008       {
2009         TapeStartPlaying();
2010
2011         game_status = PLAYING;
2012         InitGame();
2013       }
2014       else if (tape.playing)
2015       {
2016         if (tape.pausing)                       /* PAUSE -> PLAY */
2017           TapeTogglePause();
2018         else if (!tape.fast_forward)            /* PLAY -> FAST FORWARD PLAY */
2019         {
2020           tape.fast_forward = TRUE;
2021           DrawVideoDisplay(VIDEO_STATE_FFWD_ON, 0);
2022         }
2023         else if (!tape.pause_before_death)      /* FFWD PLAY -> + AUTO PAUSE */
2024         {
2025           tape.pause_before_death = TRUE;
2026           DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, VIDEO_DISPLAY_LABEL_ONLY);
2027         }
2028         else                                    /* -> NORMAL PLAY */
2029         {
2030           tape.fast_forward = FALSE;
2031           tape.pause_before_death = FALSE;
2032           DrawVideoDisplay(VIDEO_STATE_FFWD_OFF | VIDEO_STATE_PAUSE_OFF, 0);
2033         }
2034       }
2035       break;
2036
2037     default:
2038       break;
2039   }
2040
2041   BackToFront();
2042 }
2043
2044 void HandleSoundButtons(int mx, int my, int button)
2045 {
2046   if (game_status != PLAYING)
2047     return;
2048
2049   switch(CheckSoundButtons(mx,my,button))
2050   {
2051     case BUTTON_SOUND_MUSIC:
2052       if (setup.sound_music_on)
2053       { 
2054         setup.sound_music_on = FALSE;
2055         FadeSound(background_loop[level_nr % num_bg_loops]);
2056         DrawSoundDisplay(BUTTON_SOUND_MUSIC_OFF);
2057       }
2058       else if (sound_loops_allowed)
2059       { 
2060         setup.sound_on = setup.sound_music_on = TRUE;
2061         PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2062         DrawSoundDisplay(BUTTON_SOUND_MUSIC_ON);
2063       }
2064       else
2065         DrawSoundDisplay(BUTTON_SOUND_MUSIC_OFF);
2066       break;
2067
2068     case BUTTON_SOUND_LOOPS:
2069       if (setup.sound_loops_on)
2070       { 
2071         setup.sound_loops_on = FALSE;
2072         DrawSoundDisplay(BUTTON_SOUND_LOOPS_OFF);
2073       }
2074       else if (sound_loops_allowed)
2075       { 
2076         setup.sound_on = setup.sound_loops_on = TRUE;
2077         DrawSoundDisplay(BUTTON_SOUND_LOOPS_ON);
2078       }
2079       else
2080         DrawSoundDisplay(BUTTON_SOUND_LOOPS_OFF);
2081       break;
2082
2083     case BUTTON_SOUND_SIMPLE:
2084       if (setup.sound_simple_on)
2085       { 
2086         setup.sound_simple_on = FALSE;
2087         DrawSoundDisplay(BUTTON_SOUND_SIMPLE_OFF);
2088       }
2089       else if (sound_status==SOUND_AVAILABLE)
2090       { 
2091         setup.sound_on = setup.sound_simple_on = TRUE;
2092         DrawSoundDisplay(BUTTON_SOUND_SIMPLE_ON);
2093       }
2094       else
2095         DrawSoundDisplay(BUTTON_SOUND_SIMPLE_OFF);
2096       break;
2097
2098     default:
2099       break;
2100   }
2101
2102   BackToFront();
2103 }
2104
2105 void HandleGameButtons(int mx, int my, int button)
2106 {
2107   if (game_status != PLAYING)
2108     return;
2109
2110   switch(CheckGameButtons(mx,my,button))
2111   {
2112     case BUTTON_GAME_STOP:
2113       if (AllPlayersGone)
2114       {
2115         CloseDoor(DOOR_CLOSE_1);
2116         game_status = MAINMENU;
2117         DrawMainMenu();
2118         break;
2119       }
2120
2121       if (Request("Do you really want to quit the game ?",
2122                   REQ_ASK | REQ_STAY_CLOSED))
2123       { 
2124         if (options.network)
2125           SendToServer_StopPlaying();
2126         else
2127         {
2128           game_status = MAINMENU;
2129           DrawMainMenu();
2130         }
2131       }
2132       else
2133         OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2134       break;
2135
2136     case BUTTON_GAME_PAUSE:
2137       if (options.network)
2138       {
2139         if (tape.pausing)
2140           SendToServer_ContinuePlaying();
2141         else
2142           SendToServer_PausePlaying();
2143       }
2144       else
2145         TapeTogglePause();
2146
2147       /*
2148       if (tape.pausing)
2149       {
2150         if (options.network)
2151           SendToServer_ContinuePlaying();
2152         else
2153         {
2154           tape.pausing = FALSE;
2155           DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2156         }
2157       }
2158       else
2159       {
2160         if (options.network)
2161           SendToServer_PausePlaying();
2162         else
2163         {
2164           tape.pausing = TRUE;
2165           DrawVideoDisplay(VIDEO_STATE_PAUSE_ON,0);
2166         }
2167       }
2168       */
2169
2170       break;
2171
2172     case BUTTON_GAME_PLAY:
2173       if (tape.pausing)
2174       {
2175         if (options.network)
2176           SendToServer_ContinuePlaying();
2177         else
2178         {
2179           tape.pausing = FALSE;
2180           DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2181         }
2182       }
2183       break;
2184
2185     default:
2186       break;
2187   }
2188
2189   BackToFront();
2190 }