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:
251 key_joystick_mapping = 0;
256 HandleOtherEvents(&event);
262 void ClearPlayerAction()
266 /* simulate key release events for still pressed keys */
267 key_joystick_mapping = 0;
268 for (i = 0; i < MAX_PLAYERS; i++)
269 stored_player[i].action = 0;
272 void SleepWhileUnmapped()
274 boolean window_unmapped = TRUE;
276 KeyboardAutoRepeatOn();
278 while (window_unmapped)
286 case EVENT_BUTTONRELEASE:
287 button_status = MB_RELEASED;
290 case EVENT_KEYRELEASE:
291 key_joystick_mapping = 0;
294 case EVENT_MAPNOTIFY:
295 window_unmapped = FALSE;
298 case EVENT_UNMAPNOTIFY:
299 /* this is only to surely prevent the 'should not happen' case
300 * of recursively looping between 'SleepWhileUnmapped()' and
301 * 'HandleOtherEvents()' which usually calls this funtion.
306 HandleOtherEvents(&event);
311 if (game_status == GAME_MODE_PLAYING)
312 KeyboardAutoRepeatOffUnlessAutoplay();
315 void HandleExposeEvent(ExposeEvent *event)
318 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
323 void HandleButtonEvent(ButtonEvent *event)
326 printf("::: BUTTON EVENT: button %d %s\n", event->button,
327 event->type == EVENT_BUTTONPRESS ? "pressed" : "released");
330 motion_status = FALSE;
332 if (event->type == EVENT_BUTTONPRESS)
333 button_status = event->button;
335 button_status = MB_RELEASED;
337 HandleButton(event->x, event->y, button_status, event->button);
340 void HandleMotionEvent(MotionEvent *event)
342 if (!PointerInWindow(window))
343 return; /* window and pointer are on different screens */
345 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
348 motion_status = TRUE;
350 HandleButton(event->x, event->y, button_status, button_status);
353 void HandleKeyEvent(KeyEvent *event)
355 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
356 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
357 Key key = GetEventKey(event, with_modifiers);
358 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
361 printf("::: KEY EVENT: %d %s\n", GetEventKey(event, TRUE),
362 event->type == EVENT_KEYPRESS ? "pressed" : "released");
365 HandleKeyModState(keymod, key_status);
366 HandleKey(key, key_status);
369 void HandleFocusEvent(FocusChangeEvent *event)
371 static int old_joystick_status = -1;
373 if (event->type == EVENT_FOCUSOUT)
375 KeyboardAutoRepeatOn();
376 old_joystick_status = joystick.status;
377 joystick.status = JOYSTICK_NOT_AVAILABLE;
381 else if (event->type == EVENT_FOCUSIN)
383 /* When there are two Rocks'n'Diamonds windows which overlap and
384 the player moves the pointer from one game window to the other,
385 a 'FocusOut' event is generated for the window the pointer is
386 leaving and a 'FocusIn' event is generated for the window the
387 pointer is entering. In some cases, it can happen that the
388 'FocusIn' event is handled by the one game process before the
389 'FocusOut' event by the other game process. In this case the
390 X11 environment would end up with activated keyboard auto repeat,
391 because unfortunately this is a global setting and not (which
392 would be far better) set for each X11 window individually.
393 The effect would be keyboard auto repeat while playing the game
394 (game_status == GAME_MODE_PLAYING), which is not desired.
395 To avoid this special case, we just wait 1/10 second before
396 processing the 'FocusIn' event.
399 if (game_status == GAME_MODE_PLAYING)
402 KeyboardAutoRepeatOffUnlessAutoplay();
405 if (old_joystick_status != -1)
406 joystick.status = old_joystick_status;
410 void HandleClientMessageEvent(ClientMessageEvent *event)
412 if (CheckCloseWindowEvent(event))
416 void HandleButton(int mx, int my, int button, int button_nr)
418 static int old_mx = 0, old_my = 0;
432 if (HandleGadgets(mx, my, button))
434 /* do not handle this button event anymore */
435 mx = my = -32; /* force mouse event to be outside screen tiles */
438 /* do not use scroll wheel button events for anything other than gadgets */
439 if (IS_WHEEL_BUTTON(button_nr))
444 case GAME_MODE_TITLE:
445 HandleTitleScreen(mx, my, 0, 0, button);
449 HandleMainMenu(mx, my, 0, 0, button);
452 case GAME_MODE_PSEUDO_TYPENAME:
453 HandleTypeName(0, KSYM_Return);
456 case GAME_MODE_LEVELS:
457 HandleChooseLevel(mx, my, 0, 0, button);
460 case GAME_MODE_SCORES:
461 HandleHallOfFame(0, 0, 0, 0, button);
464 case GAME_MODE_EDITOR:
465 HandleLevelEditorIdle();
469 HandleInfoScreen(mx, my, 0, 0, button);
472 case GAME_MODE_SETUP:
473 HandleSetupScreen(mx, my, 0, 0, button);
476 case GAME_MODE_PLAYING:
478 if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
479 DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
488 static boolean is_string_suffix(char *string, char *suffix)
490 int string_len = strlen(string);
491 int suffix_len = strlen(suffix);
493 if (suffix_len > string_len)
496 return (strEqual(&string[string_len - suffix_len], suffix));
499 #define MAX_CHEAT_INPUT_LEN 32
501 static void HandleKeysSpecial(Key key)
503 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
504 char letter = getCharFromKey(key);
505 int cheat_input_len = strlen(cheat_input);
511 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
513 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
514 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
516 cheat_input_len = MAX_CHEAT_INPUT_LEN;
519 cheat_input[cheat_input_len++] = letter;
520 cheat_input[cheat_input_len] = '\0';
523 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
526 if (game_status == GAME_MODE_MAIN)
528 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
529 is_string_suffix(cheat_input, ":ist"))
531 InsertSolutionTape();
533 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
534 is_string_suffix(cheat_input, ":rg"))
536 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
539 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
540 is_string_suffix(cheat_input, ":rs"))
542 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
545 else if (is_string_suffix(cheat_input, ":reload-music") ||
546 is_string_suffix(cheat_input, ":rm"))
548 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
551 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
552 is_string_suffix(cheat_input, ":ra"))
554 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
555 1 << ARTWORK_TYPE_SOUNDS |
556 1 << ARTWORK_TYPE_MUSIC);
559 else if (is_string_suffix(cheat_input, ":dump-level") ||
560 is_string_suffix(cheat_input, ":dl"))
564 else if (is_string_suffix(cheat_input, ":dump-tape") ||
565 is_string_suffix(cheat_input, ":dt"))
570 else if (game_status == GAME_MODE_PLAYING)
573 if (is_string_suffix(cheat_input, ".q"))
574 DEBUG_SetMaximumDynamite();
577 else if (game_status == GAME_MODE_EDITOR)
579 if (is_string_suffix(cheat_input, ":dump-brush") ||
580 is_string_suffix(cheat_input, ":DB"))
584 else if (is_string_suffix(cheat_input, ":DDB"))
591 void HandleKey(Key key, int key_status)
593 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
594 static struct SetupKeyboardInfo custom_key;
602 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
603 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
604 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
605 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
606 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
607 { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
612 if (game_status == GAME_MODE_PLAYING)
614 /* only needed for single-step tape recording mode */
615 static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
616 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
619 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
623 if (setup.input[pnr].use_joystick)
626 custom_key = setup.input[pnr].key;
628 for (i = 0; i < 6; i++)
629 if (key == *key_info[i].key_custom)
630 key_action |= key_info[i].action;
632 if (tape.single_step && clear_button_2[pnr])
634 stored_player[pnr].action &= ~KEY_BUTTON_2;
635 clear_button_2[pnr] = FALSE;
638 if (key_status == KEY_PRESSED)
639 stored_player[pnr].action |= key_action;
641 stored_player[pnr].action &= ~key_action;
643 if (tape.single_step && tape.recording && tape.pausing)
645 if (key_status == KEY_PRESSED &&
646 (key_action & (KEY_MOTION | KEY_BUTTON_1)))
648 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
650 if (key_action & KEY_MOTION)
652 if (stored_player[pnr].action & KEY_BUTTON_2)
653 element_dropped[pnr] = TRUE;
656 else if (key_status == KEY_RELEASED &&
657 (key_action & KEY_BUTTON_2))
659 if (!element_dropped[pnr])
661 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
663 stored_player[pnr].action |= KEY_BUTTON_2;
664 clear_button_2[pnr] = TRUE;
667 element_dropped[pnr] = FALSE;
671 else if (tape.recording && tape.pausing)
673 /* prevent key release events from un-pausing a paused game */
674 if (key_status == KEY_PRESSED &&
675 (key_action & KEY_ACTION))
676 TapeTogglePause(TAPE_TOGGLE_MANUAL);
679 else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
680 TapeTogglePause(TAPE_TOGGLE_MANUAL);
686 for (i = 0; i < 6; i++)
687 if (key == key_info[i].key_default)
688 joy |= key_info[i].action;
693 if (key_status == KEY_PRESSED)
694 key_joystick_mapping |= joy;
696 key_joystick_mapping &= ~joy;
701 if (game_status != GAME_MODE_PLAYING)
702 key_joystick_mapping = 0;
704 if (key_status == KEY_RELEASED)
707 if ((key == KSYM_Return || key == KSYM_KP_Enter) &&
708 (GetKeyModState() & KMOD_Alt) && video.fullscreen_available)
710 setup.fullscreen = !setup.fullscreen;
712 ToggleFullscreenIfNeeded();
718 if (game_status == GAME_MODE_PLAYING &&
719 local_player->LevelSolved_GameEnd &&
720 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
722 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
723 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
731 if (game_status == GAME_MODE_MAIN &&
732 (key == setup.shortcut.toggle_pause || key == KSYM_space))
734 StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
739 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
741 if (key == setup.shortcut.save_game)
743 else if (key == setup.shortcut.load_game)
745 else if (key == setup.shortcut.toggle_pause)
746 TapeTogglePause(TAPE_TOGGLE_MANUAL);
749 if (game_status == GAME_MODE_PLAYING && !network_playing)
751 int centered_player_nr_next = -999;
753 if (key == setup.shortcut.focus_player_all)
754 centered_player_nr_next = -1;
756 for (i = 0; i < MAX_PLAYERS; i++)
757 if (key == setup.shortcut.focus_player[i])
758 centered_player_nr_next = i;
760 if (centered_player_nr_next != -999)
762 game.centered_player_nr_next = centered_player_nr_next;
763 game.set_centered_player = TRUE;
767 tape.centered_player_nr_next = game.centered_player_nr_next;
768 tape.set_centered_player = TRUE;
773 HandleKeysSpecial(key);
775 if (HandleGadgetsKeyInput(key))
777 if (key != KSYM_Escape) /* always allow ESC key to be handled */
778 key = KSYM_UNDEFINED;
783 case GAME_MODE_PSEUDO_TYPENAME:
784 HandleTypeName(0, key);
787 case GAME_MODE_TITLE:
789 case GAME_MODE_LEVELS:
790 case GAME_MODE_SETUP:
792 case GAME_MODE_SCORES:
797 if (game_status == GAME_MODE_TITLE)
798 HandleTitleScreen(0, 0, 0, 0, MB_MENU_CHOICE);
799 else if (game_status == GAME_MODE_MAIN)
800 HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE);
801 else if (game_status == GAME_MODE_LEVELS)
802 HandleChooseLevel(0, 0, 0, 0, MB_MENU_CHOICE);
803 else if (game_status == GAME_MODE_SETUP)
804 HandleSetupScreen(0, 0, 0, 0, MB_MENU_CHOICE);
805 else if (game_status == GAME_MODE_INFO)
806 HandleInfoScreen(0, 0, 0, 0, MB_MENU_CHOICE);
807 else if (game_status == GAME_MODE_SCORES)
808 HandleHallOfFame(0, 0, 0, 0, MB_MENU_CHOICE);
812 if (game_status == GAME_MODE_TITLE)
813 HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE);
814 else if (game_status == GAME_MODE_LEVELS)
815 HandleChooseLevel(0, 0, 0, 0, MB_MENU_LEAVE);
816 else if (game_status == GAME_MODE_SETUP)
817 HandleSetupScreen(0, 0, 0, 0, MB_MENU_LEAVE);
818 else if (game_status == GAME_MODE_INFO)
819 HandleInfoScreen(0, 0, 0, 0, MB_MENU_LEAVE);
820 else if (game_status == GAME_MODE_SCORES)
821 HandleHallOfFame(0, 0, 0, 0, MB_MENU_LEAVE);
825 if (game_status == GAME_MODE_LEVELS)
826 HandleChooseLevel(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
827 else if (game_status == GAME_MODE_SETUP)
828 HandleSetupScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
829 else if (game_status == GAME_MODE_INFO)
830 HandleInfoScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
831 else if (game_status == GAME_MODE_SCORES)
832 HandleHallOfFame(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
836 if (game_status == GAME_MODE_LEVELS)
837 HandleChooseLevel(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
838 else if (game_status == GAME_MODE_SETUP)
839 HandleSetupScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
840 else if (game_status == GAME_MODE_INFO)
841 HandleInfoScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
842 else if (game_status == GAME_MODE_SCORES)
843 HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
848 GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500);
857 case GAME_MODE_EDITOR:
858 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
859 HandleLevelEditorKeyInput(key);
862 case GAME_MODE_PLAYING:
867 RequestQuitGame(setup.ask_on_escape);
885 if (GameFrameDelay == 500)
886 GameFrameDelay = GAME_FRAME_DELAY;
888 GameFrameDelay = 500;
891 GameFrameDelay = (key - KSYM_0) * 10;
892 printf("Game speed == %d%% (%d ms delay between two frames)\n",
893 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
899 options.debug = FALSE;
900 printf("debug mode disabled\n");
904 options.debug = TRUE;
905 printf("debug mode enabled\n");
910 if (!global.fps_slowdown)
912 global.fps_slowdown = TRUE;
913 global.fps_slowdown_factor = 2;
914 printf("fps slowdown enabled -- display only every 2nd frame\n");
916 else if (global.fps_slowdown_factor == 2)
918 global.fps_slowdown_factor = 4;
919 printf("fps slowdown enabled -- display only every 4th frame\n");
923 global.fps_slowdown = FALSE;
924 global.fps_slowdown_factor = 1;
925 printf("fps slowdown disabled\n");
930 ScrollStepSize = TILEX/8;
931 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
935 ScrollStepSize = TILEX/4;
936 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
940 ScrollStepSize = TILEX/2;
941 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
945 ScrollStepSize = TILEX;
946 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
950 printf("::: currently using game engine version %d\n",
951 game.engine_version);
962 if (key == KSYM_Escape)
964 game_status = GAME_MODE_MAIN;
974 if (button_status && game_status != GAME_MODE_PLAYING)
976 HandleButton(0, 0, -button_status, button_status);
981 #if defined(NETWORK_AVALIABLE)
989 static int HandleJoystickForAllPlayers()
994 for (i = 0; i < MAX_PLAYERS; i++)
999 if (!setup.input[i].use_joystick)
1003 joy_action = Joystick(i);
1004 result |= joy_action;
1006 if (!setup.input[i].use_joystick)
1009 stored_player[i].action = joy_action;
1015 void HandleJoystick()
1017 int joystick = HandleJoystickForAllPlayers();
1018 int keyboard = key_joystick_mapping;
1019 int joy = (joystick | keyboard);
1020 int left = joy & JOY_LEFT;
1021 int right = joy & JOY_RIGHT;
1022 int up = joy & JOY_UP;
1023 int down = joy & JOY_DOWN;
1024 int button = joy & JOY_BUTTON;
1025 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1026 int dx = (left ? -1 : right ? 1 : 0);
1027 int dy = (up ? -1 : down ? 1 : 0);
1031 case GAME_MODE_TITLE:
1032 case GAME_MODE_MAIN:
1033 case GAME_MODE_LEVELS:
1034 case GAME_MODE_SETUP:
1035 case GAME_MODE_INFO:
1037 static unsigned long joystickmove_delay = 0;
1039 if (joystick && !button &&
1040 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1041 newbutton = dx = dy = 0;
1043 if (game_status == GAME_MODE_TITLE)
1044 HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1045 else if (game_status == GAME_MODE_MAIN)
1046 HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1047 else if (game_status == GAME_MODE_LEVELS)
1048 HandleChooseLevel(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1049 else if (game_status == GAME_MODE_SETUP)
1050 HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1051 else if (game_status == GAME_MODE_INFO)
1052 HandleInfoScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1056 case GAME_MODE_SCORES:
1057 HandleHallOfFame(0, 0, dx, dy, !newbutton);
1060 case GAME_MODE_EDITOR:
1061 HandleLevelEditorIdle();
1064 case GAME_MODE_PLAYING:
1065 if (tape.playing || keyboard)
1066 newbutton = ((joy & JOY_BUTTON) != 0);
1069 if (local_player->LevelSolved_GameEnd && newbutton)
1071 if (AllPlayersGone && newbutton)