rnd-20021215-1-src
[rocksndiamonds.git] / src / events.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * events.c                                                 *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "events.h"
17 #include "init.h"
18 #include "screens.h"
19 #include "tools.h"
20 #include "game.h"
21 #include "editor.h"
22 #include "files.h"
23 #include "tape.h"
24 #include "network.h"
25
26 /* values for key_status */
27 #define KEY_NOT_PRESSED         FALSE
28 #define KEY_RELEASED            FALSE
29 #define KEY_PRESSED             TRUE
30
31
32 /* event filter especially needed for SDL event filtering due to
33    delay problems with lots of mouse motion events when mouse
34    button not pressed */
35
36 int FilterMouseMotionEvents(const Event *event)
37 {
38   if (event->type != EVENT_MOTIONNOTIFY)
39     return 1;
40
41   /* get mouse motion events without pressed button only in level editor */
42   if (button_status == MB_RELEASED && game_status != LEVELED)
43     return 0;
44   else
45     return 1;
46 }
47
48 /* this is only really needed for non-SDL targets to filter unwanted events;
49    when using SDL with properly installed event filter, this function can be
50    replaced with a simple "NextEvent()" call, but it doesn't hurt either */
51
52 static boolean NextValidEvent(Event *event)
53 {
54   while (PendingEvent())
55   {
56     NextEvent(event);
57
58     if (FilterMouseMotionEvents(event))
59       return TRUE;
60   }
61
62   return FALSE;
63 }
64
65 void EventLoop(void)
66 {
67   while(1)
68   {
69     if (PendingEvent())         /* got event */
70     {
71       Event event;
72
73       if (NextValidEvent(&event))
74       {
75         switch(event.type)
76         {
77           case EVENT_BUTTONPRESS:
78           case EVENT_BUTTONRELEASE:
79             HandleButtonEvent((ButtonEvent *) &event);
80             break;
81   
82           case EVENT_MOTIONNOTIFY:
83             HandleMotionEvent((MotionEvent *) &event);
84             break;
85   
86           case EVENT_KEYPRESS:
87           case EVENT_KEYRELEASE:
88             HandleKeyEvent((KeyEvent *) &event);
89             break;
90   
91           default:
92             HandleOtherEvents(&event);
93             break;
94         }
95       }
96     }
97     else
98       HandleNoEvent();
99
100     /* don't use all CPU time when idle; the main loop while playing
101        has its own synchronization and is CPU friendly, too */
102
103     if (game_status == PLAYING)
104       HandleGameActions();
105     else
106     {
107       SyncDisplay();
108       if (!PendingEvent())      /* delay only if no pending events */
109         Delay(10);
110     }
111
112     /* refresh window contents from drawing buffer, if needed */
113     BackToFront();
114
115     if (game_status == EXITGAME)
116       return;
117   }
118 }
119
120 void HandleOtherEvents(Event *event)
121 {
122   switch(event->type)
123   {
124     case EVENT_EXPOSE:
125       HandleExposeEvent((ExposeEvent *) event);
126       break;
127
128     case EVENT_UNMAPNOTIFY:
129       SleepWhileUnmapped();
130       break;
131
132     case EVENT_FOCUSIN:
133     case EVENT_FOCUSOUT:
134       HandleFocusEvent((FocusChangeEvent *) event);
135       break;
136
137     case EVENT_CLIENTMESSAGE:
138       HandleClientMessageEvent((ClientMessageEvent *) event);
139       break;
140
141 #if defined(TARGET_SDL)
142     case SDL_JOYAXISMOTION:
143     case SDL_JOYBUTTONDOWN:
144     case SDL_JOYBUTTONUP:
145       HandleJoystickEvent(event);
146       break;
147 #endif
148
149     default:
150       break;
151   }
152 }
153
154 void ClearEventQueue()
155 {
156   while (PendingEvent())
157   {
158     Event event;
159
160     NextEvent(&event);
161
162     switch(event.type)
163     {
164       case EVENT_BUTTONRELEASE:
165         button_status = MB_RELEASED;
166         break;
167
168       case EVENT_KEYRELEASE:
169         key_joystick_mapping = 0;
170         break;
171
172       default:
173         HandleOtherEvents(&event);
174         break;
175     }
176   }
177 }
178
179 void ClearPlayerAction()
180 {
181   int i;
182
183   /* simulate key release events for still pressed keys */
184   key_joystick_mapping = 0;
185   for (i=0; i<MAX_PLAYERS; i++)
186     stored_player[i].action = 0;
187 }
188
189 void SleepWhileUnmapped()
190 {
191   boolean window_unmapped = TRUE;
192
193   KeyboardAutoRepeatOn();
194
195   while(window_unmapped)
196   {
197     Event event;
198
199     NextEvent(&event);
200
201     switch(event.type)
202     {
203       case EVENT_BUTTONRELEASE:
204         button_status = MB_RELEASED;
205         break;
206
207       case EVENT_KEYRELEASE:
208         key_joystick_mapping = 0;
209         break;
210
211       case EVENT_MAPNOTIFY:
212         window_unmapped = FALSE;
213         break;
214
215       case EVENT_UNMAPNOTIFY:
216         /* this is only to surely prevent the 'should not happen' case
217          * of recursively looping between 'SleepWhileUnmapped()' and
218          * 'HandleOtherEvents()' which usually calls this funtion.
219          */
220         break;
221
222       default:
223         HandleOtherEvents(&event);
224         break;
225     }
226   }
227
228   if (game_status == PLAYING)
229     KeyboardAutoRepeatOff();
230 }
231
232 void HandleExposeEvent(ExposeEvent *event)
233 {
234 #ifndef TARGET_SDL
235   RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
236   FlushDisplay();
237 #endif
238 }
239
240 void HandleButtonEvent(ButtonEvent *event)
241 {
242   motion_status = FALSE;
243
244   if (event->type == EVENT_BUTTONPRESS)
245     button_status = event->button;
246   else
247     button_status = MB_RELEASED;
248
249   HandleButton(event->x, event->y, button_status);
250 }
251
252 void HandleMotionEvent(MotionEvent *event)
253 {
254   if (!PointerInWindow(window))
255     return;     /* window and pointer are on different screens */
256
257 #if 1
258   if (button_status == MB_RELEASED && game_status != LEVELED)
259     return;
260 #endif
261
262   motion_status = TRUE;
263
264   HandleButton(event->x, event->y, button_status);
265 }
266
267 void HandleKeyEvent(KeyEvent *event)
268 {
269   int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
270   boolean with_modifiers = (game_status == PLAYING ? FALSE : TRUE);
271   Key key = GetEventKey(event, with_modifiers);
272
273   HandleKey(key, key_status);
274 }
275
276 void HandleFocusEvent(FocusChangeEvent *event)
277 {
278   static int old_joystick_status = -1;
279
280   if (event->type == EVENT_FOCUSOUT)
281   {
282     KeyboardAutoRepeatOn();
283     old_joystick_status = joystick.status;
284     joystick.status = JOYSTICK_NOT_AVAILABLE;
285
286     ClearPlayerAction();
287   }
288   else if (event->type == EVENT_FOCUSIN)
289   {
290     /* When there are two Rocks'n'Diamonds windows which overlap and
291        the player moves the pointer from one game window to the other,
292        a 'FocusOut' event is generated for the window the pointer is
293        leaving and a 'FocusIn' event is generated for the window the
294        pointer is entering. In some cases, it can happen that the
295        'FocusIn' event is handled by the one game process before the
296        'FocusOut' event by the other game process. In this case the
297        X11 environment would end up with activated keyboard auto repeat,
298        because unfortunately this is a global setting and not (which
299        would be far better) set for each X11 window individually.
300        The effect would be keyboard auto repeat while playing the game
301        (game_status == PLAYING), which is not desired.
302        To avoid this special case, we just wait 1/10 second before
303        processing the 'FocusIn' event.
304     */
305
306     if (game_status == PLAYING)
307     {
308       Delay(100);
309       KeyboardAutoRepeatOff();
310     }
311     if (old_joystick_status != -1)
312       joystick.status = old_joystick_status;
313   }
314 }
315
316 void HandleClientMessageEvent(ClientMessageEvent *event)
317 {
318   if (CheckCloseWindowEvent(event))
319     CloseAllAndExit(0);
320 }
321
322 void HandleButton(int mx, int my, int button)
323 {
324   static int old_mx = 0, old_my = 0;
325
326   if (button < 0)
327   {
328     mx = old_mx;
329     my = old_my;
330     button = -button;
331   }
332   else
333   {
334     old_mx = mx;
335     old_my = my;
336   }
337
338   HandleGadgets(mx, my, button);
339
340   switch(game_status)
341   {
342     case MAINMENU:
343       HandleMainMenu(mx,my, 0,0, button);
344       break;
345
346     case TYPENAME:
347       HandleTypeName(0, KSYM_Return);
348       break;
349
350     case CHOOSELEVEL:
351       HandleChooseLevel(mx,my, 0,0, button);
352       break;
353
354     case HALLOFFAME:
355       HandleHallOfFame(0,0, 0,0, button);
356       break;
357
358     case LEVELED:
359       break;
360
361     case HELPSCREEN:
362       HandleHelpScreen(button);
363       break;
364
365     case SETUP:
366       HandleSetupScreen(mx,my, 0,0, button);
367       break;
368
369     case PLAYING:
370 #ifdef DEBUG
371       if (button == MB_RELEASED)
372       {
373         int sx = (mx - SX) / TILEX;
374         int sy = (my - SY) / TILEY;
375
376         if (IN_VIS_FIELD(sx,sy))
377         {
378           int x = LEVELX(sx);
379           int y = LEVELY(sy);
380
381           printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
382
383           if (!IN_LEV_FIELD(x, y))
384             break;
385
386           printf("      Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
387           printf("      Store[%d][%d] == %d\n", x,y, Store[x][y]);
388           printf("      Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
389           printf("      StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
390           printf("      MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
391           printf("      MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
392           printf("      MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
393           printf("\n");
394         }
395       }
396 #endif
397       break;
398
399     default:
400       break;
401   }
402 }
403
404 void HandleKey(Key key, int key_status)
405 {
406   int joy = 0;
407   boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
408   static struct SetupKeyboardInfo custom_key;
409   static struct
410   {
411     Key *key_custom;
412     Key key_default;
413     byte action;
414   } key_info[] =
415   {
416     { &custom_key.left,  DEFAULT_KEY_LEFT,  JOY_LEFT     },
417     { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT    },
418     { &custom_key.up,    DEFAULT_KEY_UP,    JOY_UP       },
419     { &custom_key.down,  DEFAULT_KEY_DOWN,  JOY_DOWN     },
420     { &custom_key.snap,  DEFAULT_KEY_SNAP,  JOY_BUTTON_1 },
421     { &custom_key.bomb,  DEFAULT_KEY_BOMB,  JOY_BUTTON_2 }
422   };
423
424   if (game_status == PLAYING)
425   {
426     /* only needed for single-step tape recording mode */
427     static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
428     static boolean bomb_placed[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
429     int pnr;
430
431     for (pnr=0; pnr<MAX_PLAYERS; pnr++)
432     {
433       int i;
434       byte key_action = 0;
435
436       if (setup.input[pnr].use_joystick)
437         continue;
438
439       custom_key = setup.input[pnr].key;
440
441       for (i=0; i<6; i++)
442         if (key == *key_info[i].key_custom)
443           key_action |= key_info[i].action;
444
445       if (tape.single_step && clear_button_2[pnr])
446       {
447         stored_player[pnr].action &= ~KEY_BUTTON_2;
448         clear_button_2[pnr] = FALSE;
449       }
450
451       if (key_status == KEY_PRESSED)
452         stored_player[pnr].action |= key_action;
453       else
454         stored_player[pnr].action &= ~key_action;
455
456       if (tape.single_step && tape.recording && tape.pausing)
457       {
458         if (key_status == KEY_PRESSED &&
459             (key_action & (KEY_MOTION | KEY_BUTTON_1)))
460         {
461           TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
462
463           if (key_action & KEY_MOTION)
464           {
465             if (stored_player[pnr].action & KEY_BUTTON_2)
466               bomb_placed[pnr] = TRUE;
467           }
468         }
469         else if (key_status == KEY_RELEASED &&
470                  (key_action & KEY_BUTTON_2))
471         {
472           if (!bomb_placed[pnr])
473           {
474             TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
475
476             stored_player[pnr].action |= KEY_BUTTON_2;
477             clear_button_2[pnr] = TRUE;
478           }
479
480           bomb_placed[pnr] = FALSE;
481         }
482       }
483       else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
484         TapeTogglePause(TAPE_TOGGLE_MANUAL);
485     }
486   }
487   else
488   {
489     int i;
490
491     for (i=0; i<6; i++)
492       if (key == key_info[i].key_default)
493         joy |= key_info[i].action;
494   }
495
496   if (joy)
497   {
498     if (key_status == KEY_PRESSED)
499       key_joystick_mapping |= joy;
500     else
501       key_joystick_mapping &= ~joy;
502
503     HandleJoystick();
504   }
505
506   if (game_status != PLAYING)
507     key_joystick_mapping = 0;
508
509   if (key_status == KEY_RELEASED)
510     return;
511
512   if ((key == KSYM_Return || key == setup.shortcut.toggle_pause) &&
513       game_status == PLAYING && AllPlayersGone)
514   {
515     CloseDoor(DOOR_CLOSE_1);
516     game_status = MAINMENU;
517     DrawMainMenu();
518     return;
519   }
520
521   /* allow quick escape to the main menu with the Escape key */
522   if (key == KSYM_Escape &&
523       game_status != MAINMENU &&
524       game_status != PLAYING &&
525       game_status != LEVELED &&
526       game_status != CHOOSELEVEL &&
527       game_status != SETUP)
528   {
529     game_status = MAINMENU;
530     DrawMainMenu();
531     return;
532   }
533
534   /* special key shortcuts */
535   if (game_status == MAINMENU || game_status == PLAYING)
536   {
537     if (key == setup.shortcut.save_game)
538       TapeQuickSave();
539     else if (key == setup.shortcut.load_game)
540       TapeQuickLoad();
541     else if (key == setup.shortcut.toggle_pause)
542       TapeTogglePause(TAPE_TOGGLE_MANUAL);
543   }
544
545
546 #ifndef DEBUG
547
548   if (game_status == PLAYING && (tape.playing || tape.pausing))
549     return;
550
551 #endif
552
553
554
555   HandleGadgetsKeyInput(key);
556
557   switch(game_status)
558   {
559     case TYPENAME:
560       HandleTypeName(0, key);
561       break;
562
563     case MAINMENU:
564     case CHOOSELEVEL:
565     case SETUP:
566       switch(key)
567       {
568         case KSYM_Return:
569           if (game_status == MAINMENU)
570             HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
571           else if (game_status == CHOOSELEVEL)
572             HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
573           else if (game_status == SETUP)
574             HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
575           break;
576
577         case KSYM_Escape:
578           if (game_status == CHOOSELEVEL)
579             HandleChooseLevel(0,0, 0,0, MB_MENU_LEAVE);
580           else if (game_status == SETUP)
581             HandleSetupScreen(0,0, 0,0, MB_MENU_LEAVE);
582           break;
583
584         case KSYM_Page_Up:
585           if (game_status == CHOOSELEVEL)
586             HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
587           else if (game_status == SETUP)
588             HandleSetupScreen(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
589           break;
590
591         case KSYM_Page_Down:
592           if (game_status == CHOOSELEVEL)
593             HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
594           else if (game_status == SETUP)
595             HandleSetupScreen(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
596           break;
597
598 #ifdef DEBUG
599         case KSYM_t:
600           DumpTape(&tape);
601           break;
602 #endif
603
604         default:
605           break;
606       }
607       break;
608
609     case HELPSCREEN:
610       HandleHelpScreen(MB_RELEASED);
611       break;
612
613     case HALLOFFAME:
614       switch(key)
615       {
616         case KSYM_Return:
617           game_status = MAINMENU;
618           DrawMainMenu();
619           BackToFront();
620           break;
621
622         case KSYM_Page_Up:
623           HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
624           break;
625
626         case KSYM_Page_Down:
627           HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
628           break;
629
630         default:
631           break;
632       }
633       break;
634
635     case LEVELED:
636       if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
637         HandleLevelEditorKeyInput(key);
638       break;
639
640     case PLAYING:
641     {
642       switch(key)
643       {
644         case KSYM_Escape:
645           RequestQuitGame(setup.ask_on_escape);
646           break;
647
648 #ifdef DEBUG
649         case KSYM_0:
650         case KSYM_1:
651         case KSYM_2:
652         case KSYM_3:
653         case KSYM_4:
654         case KSYM_5:
655         case KSYM_6:
656         case KSYM_7:
657         case KSYM_8:
658         case KSYM_9:
659           if (key == KSYM_0)
660           {
661             if (GameFrameDelay == 500)
662               GameFrameDelay = GAME_FRAME_DELAY;
663             else
664               GameFrameDelay = 500;
665           }
666           else
667             GameFrameDelay = (key - KSYM_0) * 10;
668           printf("Game speed == %d%% (%d ms delay between two frames)\n",
669                  GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
670           break;
671
672         case KSYM_d:
673           if (options.debug)
674           {
675             options.debug = FALSE;
676             printf("debug mode disabled\n");
677           }
678           else
679           {
680             options.debug = TRUE;
681             printf("debug mode enabled\n");
682           }
683           break;
684
685         case KSYM_s:
686           if (!global.fps_slowdown)
687           {
688             global.fps_slowdown = TRUE;
689             global.fps_slowdown_factor = 2;
690             printf("fps slowdown enabled -- display only every 2nd frame\n");
691           }
692           else if (global.fps_slowdown_factor == 2)
693           {
694             global.fps_slowdown_factor = 4;
695             printf("fps slowdown enabled -- display only every 4th frame\n");
696           }
697           else
698           {
699             global.fps_slowdown = FALSE;
700             global.fps_slowdown_factor = 1;
701             printf("fps slowdown disabled\n");
702           }
703           break;
704
705 #if 0
706         case KSYM_a:
707           if (ScrollStepSize == TILEX/8)
708             ScrollStepSize = TILEX/4;
709           else
710             ScrollStepSize = TILEX/8;
711           printf("ScrollStepSize == %d\n", ScrollStepSize);
712           break;
713 #endif
714
715 #if 0
716         case KSYM_m:
717           if (MoveSpeed == 8)
718           {
719             MoveSpeed = 4;
720             ScrollStepSize = TILEX/4;
721           }
722           else
723           {
724             MoveSpeed = 8;
725             ScrollStepSize = TILEX/8;
726           }
727           printf("MoveSpeed == %d\n", MoveSpeed);
728           break;
729 #endif
730
731         case KSYM_f:
732           ScrollStepSize = TILEX/8;
733           printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
734           break;
735
736         case KSYM_g:
737           ScrollStepSize = TILEX/4;
738           printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
739           break;
740
741         case KSYM_h:
742           ScrollStepSize = TILEX/2;
743           printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
744           break;
745
746         case KSYM_l:
747           ScrollStepSize = TILEX;
748           printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
749           break;
750
751         case KSYM_Q:
752         case KSYM_q:
753           local_player->dynamite = 1000;
754           break;
755
756
757
758 #if 0
759
760         case KSYM_z:
761           {
762             int i;
763
764             for(i=0; i<MAX_PLAYERS; i++)
765             {
766               printf("Player %d:\n", i);
767               printf("  jx == %d, jy == %d\n",
768                      stored_player[i].jx, stored_player[i].jy);
769               printf("  last_jx == %d, last_jy == %d\n",
770                      stored_player[i].last_jx, stored_player[i].last_jy);
771             }
772             printf("\n");
773           }
774
775           break;
776 #endif
777 #endif
778
779         default:
780           break;
781       }
782       break;
783     }
784     default:
785       break;
786   }
787 }
788
789 void HandleNoEvent()
790 {
791   if (button_status && game_status != PLAYING)
792   {
793     HandleButton(0, 0, -button_status);
794     return;
795   }
796
797 #if defined(PLATFORM_UNIX)
798   if (options.network)
799     HandleNetworking();
800 #endif
801
802   HandleJoystick();
803 }
804
805 static int HandleJoystickForAllPlayers()
806 {
807   int i;
808   int result = 0;
809
810   for (i=0; i<MAX_PLAYERS; i++)
811   {
812     byte joy_action = 0;
813
814     /*
815     if (!setup.input[i].use_joystick)
816       continue;
817       */
818
819     joy_action = Joystick(i);
820     result |= joy_action;
821
822     if (!setup.input[i].use_joystick)
823       continue;
824
825     stored_player[i].action = joy_action;
826   }
827
828   return result;
829 }
830
831 void HandleJoystick()
832 {
833   int joystick  = HandleJoystickForAllPlayers();
834   int keyboard  = key_joystick_mapping;
835   int joy       = (joystick | keyboard);
836   int left      = joy & JOY_LEFT;
837   int right     = joy & JOY_RIGHT;
838   int up        = joy & JOY_UP;
839   int down      = joy & JOY_DOWN;
840   int button    = joy & JOY_BUTTON;
841   int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
842   int dx        = (left ? -1    : right ? 1     : 0);
843   int dy        = (up   ? -1    : down  ? 1     : 0);
844
845   switch(game_status)
846   {
847     case MAINMENU:
848     case CHOOSELEVEL:
849     case SETUP:
850     {
851       static unsigned long joystickmove_delay = 0;
852
853       if (joystick && !button &&
854           !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
855         newbutton = dx = dy = 0;
856
857       if (game_status == MAINMENU)
858         HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
859       else if (game_status == CHOOSELEVEL)
860         HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
861       else if (game_status == SETUP)
862         HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
863       break;
864     }
865
866     case HALLOFFAME:
867       HandleHallOfFame(0,0, dx,dy, !newbutton);
868       break;
869
870     case HELPSCREEN:
871       HandleHelpScreen(!newbutton);
872       break;
873
874     case LEVELED:
875       HandleLevelEditorIdle();
876       break;
877
878     case PLAYING:
879       if (tape.playing || keyboard)
880         newbutton = ((joy & JOY_BUTTON) != 0);
881
882       if (AllPlayersGone && newbutton)
883       {
884         CloseDoor(DOOR_CLOSE_1);
885         game_status = MAINMENU;
886         DrawMainMenu();
887         return;
888       }
889
890       break;
891
892     default:
893       break;
894   }
895 }