1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
27 #define DEBUG_EVENTS 0
30 static boolean cursor_inside_playfield = FALSE;
31 static boolean playfield_cursor_set = FALSE;
32 static unsigned long playfield_cursor_delay = 0;
35 /* event filter especially needed for SDL event filtering due to
36 delay problems with lots of mouse motion events when mouse button
37 not pressed (X11 can handle this with 'PointerMotionHintMask') */
39 int FilterMouseMotionEvents(const Event *event)
43 /* non-motion events are directly passed to event handler functions */
44 if (event->type != EVENT_MOTIONNOTIFY)
47 motion = (MotionEvent *)event;
48 cursor_inside_playfield = (motion->x >= SX && motion->x < SX + SXSIZE &&
49 motion->y >= SY && motion->y < SY + SYSIZE);
51 if (game_status == GAME_MODE_PLAYING && playfield_cursor_set)
53 SetMouseCursor(CURSOR_DEFAULT);
54 playfield_cursor_set = FALSE;
55 DelayReached(&playfield_cursor_delay, 0);
58 /* skip mouse motion events without pressed button outside level editor */
59 if (button_status == MB_RELEASED &&
60 game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
66 /* to prevent delay problems, skip mouse motion events if the very next
67 event is also a mouse motion event (and therefore effectively only
68 handling the last of a row of mouse motion events in the event queue) */
70 boolean SkipPressedMouseMotionEvent(const Event *event)
72 /* nothing to do if the current event is not a mouse motion event */
73 if (event->type != EVENT_MOTIONNOTIFY)
76 /* only skip motion events with pressed button outside level editor */
77 if (button_status == MB_RELEASED ||
78 game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
85 PeekEvent(&next_event);
87 /* if next event is also a mouse motion event, skip the current one */
88 if (next_event.type == EVENT_MOTIONNOTIFY)
95 /* this is only really needed for non-SDL targets to filter unwanted events;
96 when using SDL with properly installed event filter, this function can be
97 replaced with a simple "NextEvent()" call, but it doesn't hurt either */
99 static boolean NextValidEvent(Event *event)
101 while (PendingEvent())
103 boolean handle_this_event = FALSE;
107 if (FilterMouseMotionEvents(event))
108 handle_this_event = TRUE;
110 if (SkipPressedMouseMotionEvent(event))
111 handle_this_event = FALSE;
113 if (handle_this_event)
124 if (PendingEvent()) /* got event */
128 while (NextValidEvent(&event))
132 case EVENT_BUTTONPRESS:
133 case EVENT_BUTTONRELEASE:
134 HandleButtonEvent((ButtonEvent *) &event);
137 case EVENT_MOTIONNOTIFY:
138 HandleMotionEvent((MotionEvent *) &event);
142 case EVENT_KEYRELEASE:
143 HandleKeyEvent((KeyEvent *) &event);
147 HandleOtherEvents(&event);
154 /* when playing, display a special mouse pointer inside the playfield */
155 if (game_status == GAME_MODE_PLAYING && !tape.pausing)
157 if (!playfield_cursor_set && cursor_inside_playfield &&
158 DelayReached(&playfield_cursor_delay, 1000))
160 SetMouseCursor(CURSOR_PLAYFIELD);
161 playfield_cursor_set = TRUE;
164 else if (playfield_cursor_set)
166 SetMouseCursor(CURSOR_DEFAULT);
167 playfield_cursor_set = FALSE;
173 /* don't use all CPU time when idle; the main loop while playing
174 has its own synchronization and is CPU friendly, too */
176 if (game_status == GAME_MODE_PLAYING)
183 if (!PendingEvent()) /* delay only if no pending events */
187 /* refresh window contents from drawing buffer, if needed */
190 if (game_status == GAME_MODE_QUIT)
195 void HandleOtherEvents(Event *event)
200 HandleExposeEvent((ExposeEvent *) event);
203 case EVENT_UNMAPNOTIFY:
205 /* This causes the game to stop not only when iconified, but also
206 when on another virtual desktop, which might be not desired. */
207 SleepWhileUnmapped();
213 HandleFocusEvent((FocusChangeEvent *) event);
216 case EVENT_CLIENTMESSAGE:
217 HandleClientMessageEvent((ClientMessageEvent *) event);
220 #if defined(TARGET_SDL)
221 case SDL_JOYAXISMOTION:
222 case SDL_JOYBUTTONDOWN:
223 case SDL_JOYBUTTONUP:
224 HandleJoystickEvent(event);
233 void ClearEventQueue()
235 while (PendingEvent())
243 case EVENT_BUTTONRELEASE:
244 button_status = MB_RELEASED;
247 case EVENT_KEYRELEASE:
248 key_joystick_mapping = 0;
252 HandleOtherEvents(&event);
258 void ClearPlayerAction()
262 /* simulate key release events for still pressed keys */
263 key_joystick_mapping = 0;
264 for (i = 0; i < MAX_PLAYERS; i++)
265 stored_player[i].action = 0;
268 void SleepWhileUnmapped()
270 boolean window_unmapped = TRUE;
272 KeyboardAutoRepeatOn();
274 while (window_unmapped)
282 case EVENT_BUTTONRELEASE:
283 button_status = MB_RELEASED;
286 case EVENT_KEYRELEASE:
287 key_joystick_mapping = 0;
290 case EVENT_MAPNOTIFY:
291 window_unmapped = FALSE;
294 case EVENT_UNMAPNOTIFY:
295 /* this is only to surely prevent the 'should not happen' case
296 * of recursively looping between 'SleepWhileUnmapped()' and
297 * 'HandleOtherEvents()' which usually calls this funtion.
302 HandleOtherEvents(&event);
307 if (game_status == GAME_MODE_PLAYING)
308 KeyboardAutoRepeatOffUnlessAutoplay();
311 void HandleExposeEvent(ExposeEvent *event)
314 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
319 void HandleButtonEvent(ButtonEvent *event)
322 printf("::: BUTTON EVENT: button %d %s\n", event->button,
323 event->type == EVENT_BUTTONPRESS ? "pressed" : "released");
326 motion_status = FALSE;
328 if (event->type == EVENT_BUTTONPRESS)
329 button_status = event->button;
331 button_status = MB_RELEASED;
333 HandleButton(event->x, event->y, button_status, event->button);
336 void HandleMotionEvent(MotionEvent *event)
338 if (!PointerInWindow(window))
339 return; /* window and pointer are on different screens */
341 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
344 motion_status = TRUE;
346 HandleButton(event->x, event->y, button_status, button_status);
349 void HandleKeyEvent(KeyEvent *event)
351 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
352 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
353 Key key = GetEventKey(event, with_modifiers);
354 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
357 printf("::: KEY EVENT: %d %s\n", GetEventKey(event, TRUE),
358 event->type == EVENT_KEYPRESS ? "pressed" : "released");
361 HandleKeyModState(keymod, key_status);
362 HandleKey(key, key_status);
365 void HandleFocusEvent(FocusChangeEvent *event)
367 static int old_joystick_status = -1;
369 if (event->type == EVENT_FOCUSOUT)
371 KeyboardAutoRepeatOn();
372 old_joystick_status = joystick.status;
373 joystick.status = JOYSTICK_NOT_AVAILABLE;
377 else if (event->type == EVENT_FOCUSIN)
379 /* When there are two Rocks'n'Diamonds windows which overlap and
380 the player moves the pointer from one game window to the other,
381 a 'FocusOut' event is generated for the window the pointer is
382 leaving and a 'FocusIn' event is generated for the window the
383 pointer is entering. In some cases, it can happen that the
384 'FocusIn' event is handled by the one game process before the
385 'FocusOut' event by the other game process. In this case the
386 X11 environment would end up with activated keyboard auto repeat,
387 because unfortunately this is a global setting and not (which
388 would be far better) set for each X11 window individually.
389 The effect would be keyboard auto repeat while playing the game
390 (game_status == GAME_MODE_PLAYING), which is not desired.
391 To avoid this special case, we just wait 1/10 second before
392 processing the 'FocusIn' event.
395 if (game_status == GAME_MODE_PLAYING)
398 KeyboardAutoRepeatOffUnlessAutoplay();
401 if (old_joystick_status != -1)
402 joystick.status = old_joystick_status;
406 void HandleClientMessageEvent(ClientMessageEvent *event)
408 if (CheckCloseWindowEvent(event))
412 void HandleButton(int mx, int my, int button, int button_nr)
414 static int old_mx = 0, old_my = 0;
428 if (HandleGadgets(mx, my, button))
430 /* do not handle this button event anymore */
431 mx = my = -32; /* force mouse event to be outside screen tiles */
434 /* do not use scroll wheel button events for anything other than gadgets */
435 if (IS_WHEEL_BUTTON(button_nr))
440 case GAME_MODE_TITLE:
441 HandleTitleScreen(mx, my, 0, 0, button);
445 HandleMainMenu(mx, my, 0, 0, button);
448 case GAME_MODE_PSEUDO_TYPENAME:
449 HandleTypeName(0, KSYM_Return);
452 case GAME_MODE_LEVELS:
453 HandleChooseLevel(mx, my, 0, 0, button);
456 case GAME_MODE_SCORES:
457 HandleHallOfFame(0, 0, 0, 0, button);
460 case GAME_MODE_EDITOR:
461 HandleLevelEditorIdle();
465 HandleInfoScreen(mx, my, 0, 0, button);
468 case GAME_MODE_SETUP:
469 HandleSetupScreen(mx, my, 0, 0, button);
472 case GAME_MODE_PLAYING:
474 if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
475 DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
484 static boolean is_string_suffix(char *string, char *suffix)
486 int string_len = strlen(string);
487 int suffix_len = strlen(suffix);
489 if (suffix_len > string_len)
492 return (strEqual(&string[string_len - suffix_len], suffix));
495 #define MAX_CHEAT_INPUT_LEN 32
497 static void HandleKeysSpecial(Key key)
499 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
500 char letter = getCharFromKey(key);
501 int cheat_input_len = strlen(cheat_input);
507 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
509 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
510 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
512 cheat_input_len = MAX_CHEAT_INPUT_LEN;
515 cheat_input[cheat_input_len++] = letter;
516 cheat_input[cheat_input_len] = '\0';
519 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
522 if (game_status == GAME_MODE_MAIN)
524 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
525 is_string_suffix(cheat_input, ":ist"))
527 InsertSolutionTape();
529 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
530 is_string_suffix(cheat_input, ":rg"))
532 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
535 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
536 is_string_suffix(cheat_input, ":rs"))
538 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
541 else if (is_string_suffix(cheat_input, ":reload-music") ||
542 is_string_suffix(cheat_input, ":rm"))
544 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
547 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
548 is_string_suffix(cheat_input, ":ra"))
550 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
551 1 << ARTWORK_TYPE_SOUNDS |
552 1 << ARTWORK_TYPE_MUSIC);
555 else if (is_string_suffix(cheat_input, ":dump-level") ||
556 is_string_suffix(cheat_input, ":dl"))
560 else if (is_string_suffix(cheat_input, ":dump-tape") ||
561 is_string_suffix(cheat_input, ":dt"))
566 else if (game_status == GAME_MODE_PLAYING)
569 if (is_string_suffix(cheat_input, ".q"))
570 DEBUG_SetMaximumDynamite();
573 else if (game_status == GAME_MODE_EDITOR)
575 if (is_string_suffix(cheat_input, ":dump-brush") ||
576 is_string_suffix(cheat_input, ":DB"))
580 else if (is_string_suffix(cheat_input, ":DDB"))
587 void HandleKey(Key key, int key_status)
589 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
590 static struct SetupKeyboardInfo custom_key;
598 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
599 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
600 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
601 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
602 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
603 { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
608 if (game_status == GAME_MODE_PLAYING)
610 /* only needed for single-step tape recording mode */
611 static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
612 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
615 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
619 if (setup.input[pnr].use_joystick)
622 custom_key = setup.input[pnr].key;
624 for (i = 0; i < 6; i++)
625 if (key == *key_info[i].key_custom)
626 key_action |= key_info[i].action;
628 if (tape.single_step && clear_button_2[pnr])
630 stored_player[pnr].action &= ~KEY_BUTTON_2;
631 clear_button_2[pnr] = FALSE;
634 if (key_status == KEY_PRESSED)
635 stored_player[pnr].action |= key_action;
637 stored_player[pnr].action &= ~key_action;
639 if (tape.single_step && tape.recording && tape.pausing)
641 if (key_status == KEY_PRESSED &&
642 (key_action & (KEY_MOTION | KEY_BUTTON_1)))
644 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
646 if (key_action & KEY_MOTION)
648 if (stored_player[pnr].action & KEY_BUTTON_2)
649 element_dropped[pnr] = TRUE;
652 else if (key_status == KEY_RELEASED &&
653 (key_action & KEY_BUTTON_2))
655 if (!element_dropped[pnr])
657 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
659 stored_player[pnr].action |= KEY_BUTTON_2;
660 clear_button_2[pnr] = TRUE;
663 element_dropped[pnr] = FALSE;
666 else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
667 TapeTogglePause(TAPE_TOGGLE_MANUAL);
672 for (i = 0; i < 6; i++)
673 if (key == key_info[i].key_default)
674 joy |= key_info[i].action;
679 if (key_status == KEY_PRESSED)
680 key_joystick_mapping |= joy;
682 key_joystick_mapping &= ~joy;
687 if (game_status != GAME_MODE_PLAYING)
688 key_joystick_mapping = 0;
690 if (key_status == KEY_RELEASED)
693 if ((key == KSYM_Return || key == KSYM_KP_Enter) &&
694 (GetKeyModState() & KMOD_Alt) && video.fullscreen_available)
696 setup.fullscreen = !setup.fullscreen;
698 ToggleFullscreenIfNeeded();
703 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
704 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
711 if (game_status == GAME_MODE_MAIN &&
712 (key == setup.shortcut.toggle_pause || key == KSYM_space))
714 StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
719 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
721 if (key == setup.shortcut.save_game)
723 else if (key == setup.shortcut.load_game)
725 else if (key == setup.shortcut.toggle_pause)
726 TapeTogglePause(TAPE_TOGGLE_MANUAL);
729 if (game_status == GAME_MODE_PLAYING && !network_playing)
731 int centered_player_nr_next = -999;
733 if (key == setup.shortcut.focus_player_all)
734 centered_player_nr_next = -1;
736 for (i = 0; i < MAX_PLAYERS; i++)
737 if (key == setup.shortcut.focus_player[i])
738 centered_player_nr_next = i;
740 if (centered_player_nr_next != -999)
742 game.centered_player_nr_next = centered_player_nr_next;
743 game.set_centered_player = TRUE;
747 tape.centered_player_nr_next = game.centered_player_nr_next;
748 tape.set_centered_player = TRUE;
753 HandleKeysSpecial(key);
755 if (HandleGadgetsKeyInput(key))
757 if (key != KSYM_Escape) /* always allow ESC key to be handled */
758 key = KSYM_UNDEFINED;
763 case GAME_MODE_PSEUDO_TYPENAME:
764 HandleTypeName(0, key);
767 case GAME_MODE_TITLE:
769 case GAME_MODE_LEVELS:
770 case GAME_MODE_SETUP:
772 case GAME_MODE_SCORES:
777 if (game_status == GAME_MODE_TITLE)
778 HandleTitleScreen(0, 0, 0, 0, MB_MENU_CHOICE);
779 else if (game_status == GAME_MODE_MAIN)
780 HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE);
781 else if (game_status == GAME_MODE_LEVELS)
782 HandleChooseLevel(0, 0, 0, 0, MB_MENU_CHOICE);
783 else if (game_status == GAME_MODE_SETUP)
784 HandleSetupScreen(0, 0, 0, 0, MB_MENU_CHOICE);
785 else if (game_status == GAME_MODE_INFO)
786 HandleInfoScreen(0, 0, 0, 0, MB_MENU_CHOICE);
787 else if (game_status == GAME_MODE_SCORES)
788 HandleHallOfFame(0, 0, 0, 0, MB_MENU_CHOICE);
792 if (game_status == GAME_MODE_TITLE)
793 HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE);
794 else if (game_status == GAME_MODE_LEVELS)
795 HandleChooseLevel(0, 0, 0, 0, MB_MENU_LEAVE);
796 else if (game_status == GAME_MODE_SETUP)
797 HandleSetupScreen(0, 0, 0, 0, MB_MENU_LEAVE);
798 else if (game_status == GAME_MODE_INFO)
799 HandleInfoScreen(0, 0, 0, 0, MB_MENU_LEAVE);
800 else if (game_status == GAME_MODE_SCORES)
801 HandleHallOfFame(0, 0, 0, 0, MB_MENU_LEAVE);
805 if (game_status == GAME_MODE_LEVELS)
806 HandleChooseLevel(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
807 else if (game_status == GAME_MODE_SETUP)
808 HandleSetupScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
809 else if (game_status == GAME_MODE_INFO)
810 HandleInfoScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
811 else if (game_status == GAME_MODE_SCORES)
812 HandleHallOfFame(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
816 if (game_status == GAME_MODE_LEVELS)
817 HandleChooseLevel(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
818 else if (game_status == GAME_MODE_SETUP)
819 HandleSetupScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
820 else if (game_status == GAME_MODE_INFO)
821 HandleInfoScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
822 else if (game_status == GAME_MODE_SCORES)
823 HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
828 GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500);
837 case GAME_MODE_EDITOR:
838 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
839 HandleLevelEditorKeyInput(key);
842 case GAME_MODE_PLAYING:
847 RequestQuitGame(setup.ask_on_escape);
865 if (GameFrameDelay == 500)
866 GameFrameDelay = GAME_FRAME_DELAY;
868 GameFrameDelay = 500;
871 GameFrameDelay = (key - KSYM_0) * 10;
872 printf("Game speed == %d%% (%d ms delay between two frames)\n",
873 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
879 options.debug = FALSE;
880 printf("debug mode disabled\n");
884 options.debug = TRUE;
885 printf("debug mode enabled\n");
890 if (!global.fps_slowdown)
892 global.fps_slowdown = TRUE;
893 global.fps_slowdown_factor = 2;
894 printf("fps slowdown enabled -- display only every 2nd frame\n");
896 else if (global.fps_slowdown_factor == 2)
898 global.fps_slowdown_factor = 4;
899 printf("fps slowdown enabled -- display only every 4th frame\n");
903 global.fps_slowdown = FALSE;
904 global.fps_slowdown_factor = 1;
905 printf("fps slowdown disabled\n");
910 ScrollStepSize = TILEX/8;
911 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
915 ScrollStepSize = TILEX/4;
916 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
920 ScrollStepSize = TILEX/2;
921 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
925 ScrollStepSize = TILEX;
926 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
930 printf("::: currently using game engine version %d\n",
931 game.engine_version);
942 if (key == KSYM_Escape)
944 game_status = GAME_MODE_MAIN;
954 if (button_status && game_status != GAME_MODE_PLAYING)
956 HandleButton(0, 0, -button_status, button_status);
961 #if defined(NETWORK_AVALIABLE)
969 static int HandleJoystickForAllPlayers()
974 for (i = 0; i < MAX_PLAYERS; i++)
979 if (!setup.input[i].use_joystick)
983 joy_action = Joystick(i);
984 result |= joy_action;
986 if (!setup.input[i].use_joystick)
989 stored_player[i].action = joy_action;
995 void HandleJoystick()
997 int joystick = HandleJoystickForAllPlayers();
998 int keyboard = key_joystick_mapping;
999 int joy = (joystick | keyboard);
1000 int left = joy & JOY_LEFT;
1001 int right = joy & JOY_RIGHT;
1002 int up = joy & JOY_UP;
1003 int down = joy & JOY_DOWN;
1004 int button = joy & JOY_BUTTON;
1005 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1006 int dx = (left ? -1 : right ? 1 : 0);
1007 int dy = (up ? -1 : down ? 1 : 0);
1011 case GAME_MODE_TITLE:
1012 case GAME_MODE_MAIN:
1013 case GAME_MODE_LEVELS:
1014 case GAME_MODE_SETUP:
1015 case GAME_MODE_INFO:
1017 static unsigned long joystickmove_delay = 0;
1019 if (joystick && !button &&
1020 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1021 newbutton = dx = dy = 0;
1023 if (game_status == GAME_MODE_TITLE)
1024 HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1025 else if (game_status == GAME_MODE_MAIN)
1026 HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1027 else if (game_status == GAME_MODE_LEVELS)
1028 HandleChooseLevel(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1029 else if (game_status == GAME_MODE_SETUP)
1030 HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1031 else if (game_status == GAME_MODE_INFO)
1032 HandleInfoScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1036 case GAME_MODE_SCORES:
1037 HandleHallOfFame(0, 0, dx, dy, !newbutton);
1040 case GAME_MODE_EDITOR:
1041 HandleLevelEditorIdle();
1044 case GAME_MODE_PLAYING:
1045 if (tape.playing || keyboard)
1046 newbutton = ((joy & JOY_BUTTON) != 0);
1048 if (AllPlayersGone && newbutton)