1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
27 static boolean cursor_inside_playfield = FALSE;
28 static boolean playfield_cursor_set = FALSE;
29 static unsigned long playfield_cursor_delay = 0;
32 /* event filter especially needed for SDL event filtering due to
33 delay problems with lots of mouse motion events when mouse button
34 not pressed (X11 can handle this with 'PointerMotionHintMask') */
36 int FilterMouseMotionEvents(const Event *event)
40 /* non-motion events are directly passed to event handler functions */
41 if (event->type != EVENT_MOTIONNOTIFY)
44 motion = (MotionEvent *)event;
45 cursor_inside_playfield = (motion->x >= SX && motion->x < SX + SXSIZE &&
46 motion->y >= SY && motion->y < SY + SYSIZE);
48 if (game_status == GAME_MODE_PLAYING && playfield_cursor_set)
50 SetMouseCursor(CURSOR_DEFAULT);
51 playfield_cursor_set = FALSE;
52 DelayReached(&playfield_cursor_delay, 0);
55 /* skip mouse motion events without pressed button outside level editor */
56 if (button_status == MB_RELEASED &&
57 game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
63 /* to prevent delay problems, skip mouse motion events if the very next
64 event is also a mouse motion event (and therefore effectively only
65 handling the last of a row of mouse motion events in the event queue) */
67 boolean SkipPressedMouseMotionEvent(const Event *event)
69 /* nothing to do if the current event is not a mouse motion event */
70 if (event->type != EVENT_MOTIONNOTIFY)
73 /* only skip motion events with pressed button outside level editor */
74 if (button_status == MB_RELEASED ||
75 game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
82 PeekEvent(&next_event);
84 /* if next event is also a mouse motion event, skip the current one */
85 if (next_event.type == EVENT_MOTIONNOTIFY)
92 /* this is only really needed for non-SDL targets to filter unwanted events;
93 when using SDL with properly installed event filter, this function can be
94 replaced with a simple "NextEvent()" call, but it doesn't hurt either */
96 static boolean NextValidEvent(Event *event)
98 while (PendingEvent())
100 boolean handle_this_event = FALSE;
104 if (FilterMouseMotionEvents(event))
105 handle_this_event = TRUE;
107 if (SkipPressedMouseMotionEvent(event))
108 handle_this_event = FALSE;
110 if (handle_this_event)
121 if (PendingEvent()) /* got event */
125 while (NextValidEvent(&event))
129 case EVENT_BUTTONPRESS:
130 case EVENT_BUTTONRELEASE:
131 HandleButtonEvent((ButtonEvent *) &event);
134 case EVENT_MOTIONNOTIFY:
135 HandleMotionEvent((MotionEvent *) &event);
139 case EVENT_KEYRELEASE:
140 HandleKeyEvent((KeyEvent *) &event);
144 HandleOtherEvents(&event);
151 /* when playing, display a special mouse pointer inside the playfield */
152 if (game_status == GAME_MODE_PLAYING && !tape.pausing)
154 if (!playfield_cursor_set && cursor_inside_playfield &&
155 DelayReached(&playfield_cursor_delay, 1000))
157 SetMouseCursor(CURSOR_PLAYFIELD);
158 playfield_cursor_set = TRUE;
161 else if (playfield_cursor_set)
163 SetMouseCursor(CURSOR_DEFAULT);
164 playfield_cursor_set = FALSE;
170 /* don't use all CPU time when idle; the main loop while playing
171 has its own synchronization and is CPU friendly, too */
173 if (game_status == GAME_MODE_PLAYING)
180 if (!PendingEvent()) /* delay only if no pending events */
184 /* refresh window contents from drawing buffer, if needed */
187 if (game_status == GAME_MODE_QUIT)
192 void HandleOtherEvents(Event *event)
197 HandleExposeEvent((ExposeEvent *) event);
200 case EVENT_UNMAPNOTIFY:
202 /* This causes the game to stop not only when iconified, but also
203 when on another virtual desktop, which might be not desired. */
204 SleepWhileUnmapped();
210 HandleFocusEvent((FocusChangeEvent *) event);
213 case EVENT_CLIENTMESSAGE:
214 HandleClientMessageEvent((ClientMessageEvent *) event);
217 #if defined(TARGET_SDL)
218 case SDL_JOYAXISMOTION:
219 case SDL_JOYBUTTONDOWN:
220 case SDL_JOYBUTTONUP:
221 HandleJoystickEvent(event);
230 void ClearEventQueue()
232 while (PendingEvent())
240 case EVENT_BUTTONRELEASE:
241 button_status = MB_RELEASED;
244 case EVENT_KEYRELEASE:
245 key_joystick_mapping = 0;
249 HandleOtherEvents(&event);
255 void ClearPlayerAction()
259 /* simulate key release events for still pressed keys */
260 key_joystick_mapping = 0;
261 for (i = 0; i < MAX_PLAYERS; i++)
262 stored_player[i].action = 0;
265 void SleepWhileUnmapped()
267 boolean window_unmapped = TRUE;
269 KeyboardAutoRepeatOn();
271 while (window_unmapped)
279 case EVENT_BUTTONRELEASE:
280 button_status = MB_RELEASED;
283 case EVENT_KEYRELEASE:
284 key_joystick_mapping = 0;
287 case EVENT_MAPNOTIFY:
288 window_unmapped = FALSE;
291 case EVENT_UNMAPNOTIFY:
292 /* this is only to surely prevent the 'should not happen' case
293 * of recursively looping between 'SleepWhileUnmapped()' and
294 * 'HandleOtherEvents()' which usually calls this funtion.
299 HandleOtherEvents(&event);
304 if (game_status == GAME_MODE_PLAYING)
305 KeyboardAutoRepeatOffUnlessAutoplay();
308 void HandleExposeEvent(ExposeEvent *event)
311 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
316 void HandleButtonEvent(ButtonEvent *event)
319 printf("::: BUTTON EVENT: button %d %s\n", event->button,
320 event->type == EVENT_BUTTONPRESS ? "pressed" : "released");
323 motion_status = FALSE;
325 if (event->type == EVENT_BUTTONPRESS)
326 button_status = event->button;
328 button_status = MB_RELEASED;
330 HandleButton(event->x, event->y, button_status, event->button);
333 void HandleMotionEvent(MotionEvent *event)
335 if (!PointerInWindow(window))
336 return; /* window and pointer are on different screens */
338 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
341 motion_status = TRUE;
343 HandleButton(event->x, event->y, button_status, button_status);
346 void HandleKeyEvent(KeyEvent *event)
348 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
349 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
350 Key key = GetEventKey(event, with_modifiers);
351 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
354 printf("::: KEY EVENT: %d %s\n", GetEventKey(event, TRUE),
355 event->type == EVENT_KEYPRESS ? "pressed" : "released");
358 HandleKeyModState(keymod, key_status);
359 HandleKey(key, key_status);
362 void HandleFocusEvent(FocusChangeEvent *event)
364 static int old_joystick_status = -1;
366 if (event->type == EVENT_FOCUSOUT)
368 KeyboardAutoRepeatOn();
369 old_joystick_status = joystick.status;
370 joystick.status = JOYSTICK_NOT_AVAILABLE;
374 else if (event->type == EVENT_FOCUSIN)
376 /* When there are two Rocks'n'Diamonds windows which overlap and
377 the player moves the pointer from one game window to the other,
378 a 'FocusOut' event is generated for the window the pointer is
379 leaving and a 'FocusIn' event is generated for the window the
380 pointer is entering. In some cases, it can happen that the
381 'FocusIn' event is handled by the one game process before the
382 'FocusOut' event by the other game process. In this case the
383 X11 environment would end up with activated keyboard auto repeat,
384 because unfortunately this is a global setting and not (which
385 would be far better) set for each X11 window individually.
386 The effect would be keyboard auto repeat while playing the game
387 (game_status == GAME_MODE_PLAYING), which is not desired.
388 To avoid this special case, we just wait 1/10 second before
389 processing the 'FocusIn' event.
392 if (game_status == GAME_MODE_PLAYING)
395 KeyboardAutoRepeatOffUnlessAutoplay();
398 if (old_joystick_status != -1)
399 joystick.status = old_joystick_status;
403 void HandleClientMessageEvent(ClientMessageEvent *event)
405 if (CheckCloseWindowEvent(event))
409 void HandleButton(int mx, int my, int button, int button_nr)
411 static int old_mx = 0, old_my = 0;
425 if (HandleGadgets(mx, my, button))
427 /* do not handle this button event anymore */
428 mx = my = -32; /* force mouse event to be outside screen tiles */
431 /* do not use scroll wheel button events for anything other than gadgets */
432 if (IS_WHEEL_BUTTON(button_nr))
437 case GAME_MODE_TITLE:
438 HandleTitleScreen(mx, my, 0, 0, button);
442 HandleMainMenu(mx, my, 0, 0, button);
445 case GAME_MODE_PSEUDO_TYPENAME:
446 HandleTypeName(0, KSYM_Return);
449 case GAME_MODE_LEVELS:
450 HandleChooseLevel(mx, my, 0, 0, button);
453 case GAME_MODE_SCORES:
454 HandleHallOfFame(0, 0, 0, 0, button);
457 case GAME_MODE_EDITOR:
458 HandleLevelEditorIdle();
462 HandleInfoScreen(mx, my, 0, 0, button);
465 case GAME_MODE_SETUP:
466 HandleSetupScreen(mx, my, 0, 0, button);
469 case GAME_MODE_PLAYING:
471 if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
472 DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
481 static boolean is_string_suffix(char *string, char *suffix)
483 int string_len = strlen(string);
484 int suffix_len = strlen(suffix);
486 if (suffix_len > string_len)
489 return (strEqual(&string[string_len - suffix_len], suffix));
492 #define MAX_CHEAT_INPUT_LEN 32
494 static void HandleKeysSpecial(Key key)
496 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
497 char letter = getCharFromKey(key);
498 int cheat_input_len = strlen(cheat_input);
504 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
506 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
507 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
509 cheat_input_len = MAX_CHEAT_INPUT_LEN;
512 cheat_input[cheat_input_len++] = letter;
513 cheat_input[cheat_input_len] = '\0';
516 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
519 if (game_status == GAME_MODE_MAIN)
521 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
522 is_string_suffix(cheat_input, ":ist"))
524 InsertSolutionTape();
526 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
527 is_string_suffix(cheat_input, ":rg"))
529 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
532 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
533 is_string_suffix(cheat_input, ":rs"))
535 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
538 else if (is_string_suffix(cheat_input, ":reload-music") ||
539 is_string_suffix(cheat_input, ":rm"))
541 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
544 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
545 is_string_suffix(cheat_input, ":ra"))
547 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
548 1 << ARTWORK_TYPE_SOUNDS |
549 1 << ARTWORK_TYPE_MUSIC);
552 else if (is_string_suffix(cheat_input, ":dump-level") ||
553 is_string_suffix(cheat_input, ":dl"))
557 else if (is_string_suffix(cheat_input, ":dump-tape") ||
558 is_string_suffix(cheat_input, ":dt"))
563 else if (game_status == GAME_MODE_PLAYING)
566 if (is_string_suffix(cheat_input, ".q"))
567 DEBUG_SetMaximumDynamite();
570 else if (game_status == GAME_MODE_EDITOR)
572 if (is_string_suffix(cheat_input, ":dump-brush") ||
573 is_string_suffix(cheat_input, ":DB"))
577 else if (is_string_suffix(cheat_input, ":DDB"))
584 void HandleKey(Key key, int key_status)
586 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
587 static struct SetupKeyboardInfo custom_key;
595 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
596 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
597 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
598 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
599 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
600 { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
605 if (game_status == GAME_MODE_PLAYING)
607 /* only needed for single-step tape recording mode */
608 static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
609 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
612 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
616 if (setup.input[pnr].use_joystick)
619 custom_key = setup.input[pnr].key;
621 for (i = 0; i < 6; i++)
622 if (key == *key_info[i].key_custom)
623 key_action |= key_info[i].action;
625 if (tape.single_step && clear_button_2[pnr])
627 stored_player[pnr].action &= ~KEY_BUTTON_2;
628 clear_button_2[pnr] = FALSE;
631 if (key_status == KEY_PRESSED)
632 stored_player[pnr].action |= key_action;
634 stored_player[pnr].action &= ~key_action;
636 if (tape.single_step && tape.recording && tape.pausing)
638 if (key_status == KEY_PRESSED &&
639 (key_action & (KEY_MOTION | KEY_BUTTON_1)))
641 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
643 if (key_action & KEY_MOTION)
645 if (stored_player[pnr].action & KEY_BUTTON_2)
646 element_dropped[pnr] = TRUE;
649 else if (key_status == KEY_RELEASED &&
650 (key_action & KEY_BUTTON_2))
652 if (!element_dropped[pnr])
654 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
656 stored_player[pnr].action |= KEY_BUTTON_2;
657 clear_button_2[pnr] = TRUE;
660 element_dropped[pnr] = FALSE;
663 else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
664 TapeTogglePause(TAPE_TOGGLE_MANUAL);
669 for (i = 0; i < 6; i++)
670 if (key == key_info[i].key_default)
671 joy |= key_info[i].action;
676 if (key_status == KEY_PRESSED)
677 key_joystick_mapping |= joy;
679 key_joystick_mapping &= ~joy;
684 if (game_status != GAME_MODE_PLAYING)
685 key_joystick_mapping = 0;
687 if (key_status == KEY_RELEASED)
690 if ((key == KSYM_Return || key == KSYM_KP_Enter) &&
691 (GetKeyModState() & KMOD_Alt) && video.fullscreen_available)
693 setup.fullscreen = !setup.fullscreen;
695 ToggleFullscreenIfNeeded();
700 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
701 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
706 CloseDoor(DOOR_CLOSE_1);
707 game_status = GAME_MODE_MAIN;
714 if (game_status == GAME_MODE_MAIN &&
715 (key == setup.shortcut.toggle_pause || key == KSYM_space))
717 StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
722 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
724 if (key == setup.shortcut.save_game)
726 else if (key == setup.shortcut.load_game)
728 else if (key == setup.shortcut.toggle_pause)
729 TapeTogglePause(TAPE_TOGGLE_MANUAL);
732 if (game_status == GAME_MODE_PLAYING && !network_playing)
734 int centered_player_nr_next = -999;
736 if (key == setup.shortcut.focus_player_all)
737 centered_player_nr_next = -1;
739 for (i = 0; i < MAX_PLAYERS; i++)
740 if (key == setup.shortcut.focus_player[i])
741 centered_player_nr_next = i;
743 if (centered_player_nr_next != -999)
745 game.centered_player_nr_next = centered_player_nr_next;
746 game.set_centered_player = TRUE;
750 tape.centered_player_nr_next = game.centered_player_nr_next;
751 tape.set_centered_player = TRUE;
756 HandleKeysSpecial(key);
758 if (HandleGadgetsKeyInput(key))
760 if (key != KSYM_Escape) /* always allow ESC key to be handled */
761 key = KSYM_UNDEFINED;
766 case GAME_MODE_PSEUDO_TYPENAME:
767 HandleTypeName(0, key);
770 case GAME_MODE_TITLE:
772 case GAME_MODE_LEVELS:
773 case GAME_MODE_SETUP:
775 case GAME_MODE_SCORES:
780 if (game_status == GAME_MODE_TITLE)
781 HandleTitleScreen(0, 0, 0, 0, MB_MENU_CHOICE);
782 else if (game_status == GAME_MODE_MAIN)
783 HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE);
784 else if (game_status == GAME_MODE_LEVELS)
785 HandleChooseLevel(0, 0, 0, 0, MB_MENU_CHOICE);
786 else if (game_status == GAME_MODE_SETUP)
787 HandleSetupScreen(0, 0, 0, 0, MB_MENU_CHOICE);
788 else if (game_status == GAME_MODE_INFO)
789 HandleInfoScreen(0, 0, 0, 0, MB_MENU_CHOICE);
790 else if (game_status == GAME_MODE_SCORES)
791 HandleHallOfFame(0, 0, 0, 0, MB_MENU_CHOICE);
795 if (game_status == GAME_MODE_TITLE)
796 HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE);
797 else if (game_status == GAME_MODE_LEVELS)
798 HandleChooseLevel(0, 0, 0, 0, MB_MENU_LEAVE);
799 else if (game_status == GAME_MODE_SETUP)
800 HandleSetupScreen(0, 0, 0, 0, MB_MENU_LEAVE);
801 else if (game_status == GAME_MODE_INFO)
802 HandleInfoScreen(0, 0, 0, 0, MB_MENU_LEAVE);
803 else if (game_status == GAME_MODE_SCORES)
804 HandleHallOfFame(0, 0, 0, 0, MB_MENU_LEAVE);
808 if (game_status == GAME_MODE_LEVELS)
809 HandleChooseLevel(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
810 else if (game_status == GAME_MODE_SETUP)
811 HandleSetupScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
812 else if (game_status == GAME_MODE_INFO)
813 HandleInfoScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
814 else if (game_status == GAME_MODE_SCORES)
815 HandleHallOfFame(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
819 if (game_status == GAME_MODE_LEVELS)
820 HandleChooseLevel(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
821 else if (game_status == GAME_MODE_SETUP)
822 HandleSetupScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
823 else if (game_status == GAME_MODE_INFO)
824 HandleInfoScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
825 else if (game_status == GAME_MODE_SCORES)
826 HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
831 GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500);
841 case GAME_MODE_SCORES:
846 HandleHallOfFame(0, 0, 0, 0, MB_MENU_CHOICE);
851 HandleHallOfFame(0, 0, 0, 0, MB_MENU_LEAVE);
853 game_status = GAME_MODE_MAIN;
859 HandleHallOfFame(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
863 HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
872 case GAME_MODE_EDITOR:
873 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
874 HandleLevelEditorKeyInput(key);
877 case GAME_MODE_PLAYING:
882 RequestQuitGame(setup.ask_on_escape);
900 if (GameFrameDelay == 500)
901 GameFrameDelay = GAME_FRAME_DELAY;
903 GameFrameDelay = 500;
906 GameFrameDelay = (key - KSYM_0) * 10;
907 printf("Game speed == %d%% (%d ms delay between two frames)\n",
908 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
914 options.debug = FALSE;
915 printf("debug mode disabled\n");
919 options.debug = TRUE;
920 printf("debug mode enabled\n");
925 if (!global.fps_slowdown)
927 global.fps_slowdown = TRUE;
928 global.fps_slowdown_factor = 2;
929 printf("fps slowdown enabled -- display only every 2nd frame\n");
931 else if (global.fps_slowdown_factor == 2)
933 global.fps_slowdown_factor = 4;
934 printf("fps slowdown enabled -- display only every 4th frame\n");
938 global.fps_slowdown = FALSE;
939 global.fps_slowdown_factor = 1;
940 printf("fps slowdown disabled\n");
945 ScrollStepSize = TILEX/8;
946 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
950 ScrollStepSize = TILEX/4;
951 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
955 ScrollStepSize = TILEX/2;
956 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
960 ScrollStepSize = TILEX;
961 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
965 printf("::: currently using game engine version %d\n",
966 game.engine_version);
977 if (key == KSYM_Escape)
979 game_status = GAME_MODE_MAIN;
989 if (button_status && game_status != GAME_MODE_PLAYING)
991 HandleButton(0, 0, -button_status, button_status);
996 #if defined(NETWORK_AVALIABLE)
1004 static int HandleJoystickForAllPlayers()
1009 for (i = 0; i < MAX_PLAYERS; i++)
1011 byte joy_action = 0;
1014 if (!setup.input[i].use_joystick)
1018 joy_action = Joystick(i);
1019 result |= joy_action;
1021 if (!setup.input[i].use_joystick)
1024 stored_player[i].action = joy_action;
1030 void HandleJoystick()
1032 int joystick = HandleJoystickForAllPlayers();
1033 int keyboard = key_joystick_mapping;
1034 int joy = (joystick | keyboard);
1035 int left = joy & JOY_LEFT;
1036 int right = joy & JOY_RIGHT;
1037 int up = joy & JOY_UP;
1038 int down = joy & JOY_DOWN;
1039 int button = joy & JOY_BUTTON;
1040 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1041 int dx = (left ? -1 : right ? 1 : 0);
1042 int dy = (up ? -1 : down ? 1 : 0);
1046 case GAME_MODE_TITLE:
1047 case GAME_MODE_MAIN:
1048 case GAME_MODE_LEVELS:
1049 case GAME_MODE_SETUP:
1050 case GAME_MODE_INFO:
1052 static unsigned long joystickmove_delay = 0;
1054 if (joystick && !button &&
1055 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1056 newbutton = dx = dy = 0;
1058 if (game_status == GAME_MODE_TITLE)
1059 HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1060 else if (game_status == GAME_MODE_MAIN)
1061 HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1062 else if (game_status == GAME_MODE_LEVELS)
1063 HandleChooseLevel(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1064 else if (game_status == GAME_MODE_SETUP)
1065 HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1066 else if (game_status == GAME_MODE_INFO)
1067 HandleInfoScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1071 case GAME_MODE_SCORES:
1072 HandleHallOfFame(0, 0, dx, dy, !newbutton);
1075 case GAME_MODE_EDITOR:
1076 HandleLevelEditorIdle();
1079 case GAME_MODE_PLAYING:
1080 if (tape.playing || keyboard)
1081 newbutton = ((joy & JOY_BUTTON) != 0);
1083 if (AllPlayersGone && newbutton)
1088 CloseDoor(DOOR_CLOSE_1);
1089 game_status = GAME_MODE_MAIN;