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 int 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);
228 HandleWindowManagerEvent(event);
237 void ClearEventQueue()
239 while (PendingEvent())
247 case EVENT_BUTTONRELEASE:
248 button_status = MB_RELEASED;
251 case EVENT_KEYRELEASE:
255 key_joystick_mapping = 0;
260 HandleOtherEvents(&event);
266 void ClearPlayerAction()
270 /* simulate key release events for still pressed keys */
271 key_joystick_mapping = 0;
272 for (i = 0; i < MAX_PLAYERS; i++)
273 stored_player[i].action = 0;
276 void SleepWhileUnmapped()
278 boolean window_unmapped = TRUE;
280 KeyboardAutoRepeatOn();
282 while (window_unmapped)
290 case EVENT_BUTTONRELEASE:
291 button_status = MB_RELEASED;
294 case EVENT_KEYRELEASE:
295 key_joystick_mapping = 0;
298 case EVENT_MAPNOTIFY:
299 window_unmapped = FALSE;
302 case EVENT_UNMAPNOTIFY:
303 /* this is only to surely prevent the 'should not happen' case
304 * of recursively looping between 'SleepWhileUnmapped()' and
305 * 'HandleOtherEvents()' which usually calls this funtion.
310 HandleOtherEvents(&event);
315 if (game_status == GAME_MODE_PLAYING)
316 KeyboardAutoRepeatOffUnlessAutoplay();
319 void HandleExposeEvent(ExposeEvent *event)
322 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
327 void HandleButtonEvent(ButtonEvent *event)
330 printf("::: BUTTON EVENT: button %d %s\n", event->button,
331 event->type == EVENT_BUTTONPRESS ? "pressed" : "released");
334 motion_status = FALSE;
336 if (event->type == EVENT_BUTTONPRESS)
337 button_status = event->button;
339 button_status = MB_RELEASED;
341 HandleButton(event->x, event->y, button_status, event->button);
344 void HandleMotionEvent(MotionEvent *event)
346 if (!PointerInWindow(window))
347 return; /* window and pointer are on different screens */
349 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
352 motion_status = TRUE;
354 HandleButton(event->x, event->y, button_status, button_status);
357 void HandleKeyEvent(KeyEvent *event)
359 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
360 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
361 Key key = GetEventKey(event, with_modifiers);
362 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
365 printf("::: KEY EVENT: %d %s\n", GetEventKey(event, TRUE),
366 event->type == EVENT_KEYPRESS ? "pressed" : "released");
369 HandleKeyModState(keymod, key_status);
370 HandleKey(key, key_status);
373 void HandleFocusEvent(FocusChangeEvent *event)
375 static int old_joystick_status = -1;
377 if (event->type == EVENT_FOCUSOUT)
379 KeyboardAutoRepeatOn();
380 old_joystick_status = joystick.status;
381 joystick.status = JOYSTICK_NOT_AVAILABLE;
385 else if (event->type == EVENT_FOCUSIN)
387 /* When there are two Rocks'n'Diamonds windows which overlap and
388 the player moves the pointer from one game window to the other,
389 a 'FocusOut' event is generated for the window the pointer is
390 leaving and a 'FocusIn' event is generated for the window the
391 pointer is entering. In some cases, it can happen that the
392 'FocusIn' event is handled by the one game process before the
393 'FocusOut' event by the other game process. In this case the
394 X11 environment would end up with activated keyboard auto repeat,
395 because unfortunately this is a global setting and not (which
396 would be far better) set for each X11 window individually.
397 The effect would be keyboard auto repeat while playing the game
398 (game_status == GAME_MODE_PLAYING), which is not desired.
399 To avoid this special case, we just wait 1/10 second before
400 processing the 'FocusIn' event.
403 if (game_status == GAME_MODE_PLAYING)
406 KeyboardAutoRepeatOffUnlessAutoplay();
409 if (old_joystick_status != -1)
410 joystick.status = old_joystick_status;
414 void HandleClientMessageEvent(ClientMessageEvent *event)
416 if (CheckCloseWindowEvent(event))
420 void HandleWindowManagerEvent(Event *event)
422 #if defined(TARGET_SDL)
423 SDLHandleWindowManagerEvent(event);
427 void HandleButton(int mx, int my, int button, int button_nr)
429 static int old_mx = 0, old_my = 0;
443 if (HandleGadgets(mx, my, button))
445 /* do not handle this button event anymore */
446 mx = my = -32; /* force mouse event to be outside screen tiles */
449 /* do not use scroll wheel button events for anything other than gadgets */
450 if (IS_WHEEL_BUTTON(button_nr))
455 case GAME_MODE_TITLE:
456 HandleTitleScreen(mx, my, 0, 0, button);
460 HandleMainMenu(mx, my, 0, 0, button);
463 case GAME_MODE_PSEUDO_TYPENAME:
464 HandleTypeName(0, KSYM_Return);
467 case GAME_MODE_LEVELS:
468 HandleChooseLevelSet(mx, my, 0, 0, button);
471 case GAME_MODE_LEVELNR:
472 HandleChooseLevelNr(mx, my, 0, 0, button);
475 case GAME_MODE_SCORES:
476 HandleHallOfFame(0, 0, 0, 0, button);
479 case GAME_MODE_EDITOR:
480 HandleLevelEditorIdle();
484 HandleInfoScreen(mx, my, 0, 0, button);
487 case GAME_MODE_SETUP:
488 HandleSetupScreen(mx, my, 0, 0, button);
491 case GAME_MODE_PLAYING:
493 if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
494 DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
503 static boolean is_string_suffix(char *string, char *suffix)
505 int string_len = strlen(string);
506 int suffix_len = strlen(suffix);
508 if (suffix_len > string_len)
511 return (strEqual(&string[string_len - suffix_len], suffix));
514 #define MAX_CHEAT_INPUT_LEN 32
516 static void HandleKeysSpecial(Key key)
518 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
519 char letter = getCharFromKey(key);
520 int cheat_input_len = strlen(cheat_input);
526 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
528 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
529 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
531 cheat_input_len = MAX_CHEAT_INPUT_LEN;
534 cheat_input[cheat_input_len++] = letter;
535 cheat_input[cheat_input_len] = '\0';
538 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
541 if (game_status == GAME_MODE_MAIN)
543 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
544 is_string_suffix(cheat_input, ":ist"))
546 InsertSolutionTape();
548 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
549 is_string_suffix(cheat_input, ":rg"))
551 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
554 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
555 is_string_suffix(cheat_input, ":rs"))
557 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
560 else if (is_string_suffix(cheat_input, ":reload-music") ||
561 is_string_suffix(cheat_input, ":rm"))
563 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
566 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
567 is_string_suffix(cheat_input, ":ra"))
569 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
570 1 << ARTWORK_TYPE_SOUNDS |
571 1 << ARTWORK_TYPE_MUSIC);
574 else if (is_string_suffix(cheat_input, ":dump-level") ||
575 is_string_suffix(cheat_input, ":dl"))
579 else if (is_string_suffix(cheat_input, ":dump-tape") ||
580 is_string_suffix(cheat_input, ":dt"))
584 else if (is_string_suffix(cheat_input, ":save-native-level") ||
585 is_string_suffix(cheat_input, ":snl"))
587 SaveNativeLevel(&level);
590 else if (game_status == GAME_MODE_PLAYING)
593 if (is_string_suffix(cheat_input, ".q"))
594 DEBUG_SetMaximumDynamite();
597 else if (game_status == GAME_MODE_EDITOR)
599 if (is_string_suffix(cheat_input, ":dump-brush") ||
600 is_string_suffix(cheat_input, ":DB"))
604 else if (is_string_suffix(cheat_input, ":DDB"))
611 void HandleKey(Key key, int key_status)
613 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
614 static struct SetupKeyboardInfo ski;
615 static struct SetupShortcutInfo ssi;
624 { &ski.left, &ssi.snap_left, DEFAULT_KEY_LEFT, JOY_LEFT },
625 { &ski.right, &ssi.snap_right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
626 { &ski.up, &ssi.snap_up, DEFAULT_KEY_UP, JOY_UP },
627 { &ski.down, &ssi.snap_down, DEFAULT_KEY_DOWN, JOY_DOWN },
628 { &ski.snap, NULL, DEFAULT_KEY_SNAP, JOY_BUTTON_SNAP },
629 { &ski.drop, NULL, DEFAULT_KEY_DROP, JOY_BUTTON_DROP }
634 if (game_status == GAME_MODE_PLAYING)
636 /* only needed for single-step tape recording mode */
637 static boolean clear_snap_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
638 static boolean clear_drop_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
639 static boolean element_snapped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
640 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
643 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
647 if (setup.input[pnr].use_joystick)
650 ski = setup.input[pnr].key;
652 for (i = 0; i < NUM_PLAYER_ACTIONS; i++)
653 if (key == *key_info[i].key_custom)
654 key_action |= key_info[i].action;
656 /* use combined snap+direction keys for the first player only */
659 ssi = setup.shortcut;
661 for (i = 0; i < NUM_DIRECTIONS; i++)
662 if (key == *key_info[i].key_snap)
663 key_action |= key_info[i].action | JOY_BUTTON_SNAP;
666 /* clear delayed snap and drop actions in single step mode (see below) */
667 if (tape.single_step)
669 if (clear_snap_button[pnr])
671 stored_player[pnr].action &= ~KEY_BUTTON_SNAP;
672 clear_snap_button[pnr] = FALSE;
675 if (clear_drop_button[pnr])
677 stored_player[pnr].action &= ~KEY_BUTTON_DROP;
678 clear_drop_button[pnr] = FALSE;
682 if (key_status == KEY_PRESSED)
683 stored_player[pnr].action |= key_action;
685 stored_player[pnr].action &= ~key_action;
687 if (tape.single_step && tape.recording && tape.pausing)
689 if (key_status == KEY_PRESSED && key_action & KEY_MOTION)
691 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
693 /* if snap key already pressed, don't snap when releasing (below) */
694 if (stored_player[pnr].action & KEY_BUTTON_SNAP)
695 element_snapped[pnr] = TRUE;
697 /* if drop key already pressed, don't drop when releasing (below) */
698 if (stored_player[pnr].action & KEY_BUTTON_DROP)
699 element_dropped[pnr] = TRUE;
702 else if (key_status == KEY_PRESSED && key_action & KEY_BUTTON_DROP)
704 if (level.game_engine_type == GAME_ENGINE_TYPE_EM ||
705 level.game_engine_type == GAME_ENGINE_TYPE_SP)
708 printf("::: drop key pressed\n");
711 if (level.game_engine_type == GAME_ENGINE_TYPE_SP &&
712 getRedDiskReleaseFlag_SP() == 0)
713 stored_player[pnr].action &= ~KEY_BUTTON_DROP;
715 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
719 else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON)
721 if (key_action & KEY_BUTTON_SNAP)
723 /* if snap key was released without moving (see above), snap now */
724 if (!element_snapped[pnr])
726 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
728 stored_player[pnr].action |= KEY_BUTTON_SNAP;
730 /* clear delayed snap button on next event */
731 clear_snap_button[pnr] = TRUE;
734 element_snapped[pnr] = FALSE;
738 if (key_action & KEY_BUTTON_DROP &&
739 level.game_engine_type == GAME_ENGINE_TYPE_RND)
741 /* if drop key was released without moving (see above), drop now */
742 if (!element_dropped[pnr])
744 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
746 if (level.game_engine_type != GAME_ENGINE_TYPE_SP ||
747 getRedDiskReleaseFlag_SP() != 0)
748 stored_player[pnr].action |= KEY_BUTTON_DROP;
750 /* clear delayed drop button on next event */
751 clear_drop_button[pnr] = TRUE;
754 element_dropped[pnr] = FALSE;
759 else if (tape.recording && tape.pausing)
761 /* prevent key release events from un-pausing a paused game */
762 if (key_status == KEY_PRESSED && key_action & KEY_ACTION)
763 TapeTogglePause(TAPE_TOGGLE_MANUAL);
769 for (i = 0; i < NUM_PLAYER_ACTIONS; i++)
770 if (key == key_info[i].key_default)
771 joy |= key_info[i].action;
776 if (key_status == KEY_PRESSED)
777 key_joystick_mapping |= joy;
779 key_joystick_mapping &= ~joy;
784 if (game_status != GAME_MODE_PLAYING)
785 key_joystick_mapping = 0;
787 if (key_status == KEY_RELEASED)
790 if ((key == KSYM_Return || key == KSYM_KP_Enter) &&
791 (GetKeyModState() & KMOD_Alt) && video.fullscreen_available)
793 setup.fullscreen = !setup.fullscreen;
795 ToggleFullscreenIfNeeded();
797 if (game_status == GAME_MODE_SETUP)
798 RedrawSetupScreenAfterFullscreenToggle();
804 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd &&
805 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
807 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
808 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
816 if (game_status == GAME_MODE_MAIN &&
817 (key == setup.shortcut.toggle_pause || key == KSYM_space))
819 StartGameActions(options.network, setup.autorecord, level.random_seed);
824 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
826 if (key == setup.shortcut.save_game)
828 else if (key == setup.shortcut.load_game)
830 else if (key == setup.shortcut.toggle_pause)
831 TapeTogglePause(TAPE_TOGGLE_MANUAL);
833 HandleTapeButtonKeys(key);
834 HandleSoundButtonKeys(key);
837 if (game_status == GAME_MODE_PLAYING && !network_playing)
839 int centered_player_nr_next = -999;
841 if (key == setup.shortcut.focus_player_all)
842 centered_player_nr_next = -1;
844 for (i = 0; i < MAX_PLAYERS; i++)
845 if (key == setup.shortcut.focus_player[i])
846 centered_player_nr_next = i;
848 if (centered_player_nr_next != -999)
850 game.centered_player_nr_next = centered_player_nr_next;
851 game.set_centered_player = TRUE;
855 tape.centered_player_nr_next = game.centered_player_nr_next;
856 tape.set_centered_player = TRUE;
861 HandleKeysSpecial(key);
863 if (HandleGadgetsKeyInput(key))
865 if (key != KSYM_Escape) /* always allow ESC key to be handled */
866 key = KSYM_UNDEFINED;
871 case GAME_MODE_PSEUDO_TYPENAME:
872 HandleTypeName(0, key);
875 case GAME_MODE_TITLE:
877 case GAME_MODE_LEVELS:
878 case GAME_MODE_LEVELNR:
879 case GAME_MODE_SETUP:
881 case GAME_MODE_SCORES:
886 if (game_status == GAME_MODE_TITLE)
887 HandleTitleScreen(0, 0, 0, 0, MB_MENU_CHOICE);
888 else if (game_status == GAME_MODE_MAIN)
889 HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE);
890 else if (game_status == GAME_MODE_LEVELS)
891 HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_CHOICE);
892 else if (game_status == GAME_MODE_LEVELNR)
893 HandleChooseLevelNr(0, 0, 0, 0, MB_MENU_CHOICE);
894 else if (game_status == GAME_MODE_SETUP)
895 HandleSetupScreen(0, 0, 0, 0, MB_MENU_CHOICE);
896 else if (game_status == GAME_MODE_INFO)
897 HandleInfoScreen(0, 0, 0, 0, MB_MENU_CHOICE);
898 else if (game_status == GAME_MODE_SCORES)
899 HandleHallOfFame(0, 0, 0, 0, MB_MENU_CHOICE);
903 if (game_status != GAME_MODE_MAIN)
904 FadeSkipNextFadeIn();
906 if (game_status == GAME_MODE_TITLE)
907 HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE);
908 else if (game_status == GAME_MODE_LEVELS)
909 HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_LEAVE);
910 else if (game_status == GAME_MODE_LEVELNR)
911 HandleChooseLevelNr(0, 0, 0, 0, MB_MENU_LEAVE);
912 else if (game_status == GAME_MODE_SETUP)
913 HandleSetupScreen(0, 0, 0, 0, MB_MENU_LEAVE);
914 else if (game_status == GAME_MODE_INFO)
915 HandleInfoScreen(0, 0, 0, 0, MB_MENU_LEAVE);
916 else if (game_status == GAME_MODE_SCORES)
917 HandleHallOfFame(0, 0, 0, 0, MB_MENU_LEAVE);
921 if (game_status == GAME_MODE_LEVELS)
922 HandleChooseLevelSet(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
923 else if (game_status == GAME_MODE_LEVELNR)
924 HandleChooseLevelNr(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
925 else if (game_status == GAME_MODE_SETUP)
926 HandleSetupScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
927 else if (game_status == GAME_MODE_INFO)
928 HandleInfoScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
929 else if (game_status == GAME_MODE_SCORES)
930 HandleHallOfFame(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
934 if (game_status == GAME_MODE_LEVELS)
935 HandleChooseLevelSet(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
936 else if (game_status == GAME_MODE_LEVELNR)
937 HandleChooseLevelNr(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
938 else if (game_status == GAME_MODE_SETUP)
939 HandleSetupScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
940 else if (game_status == GAME_MODE_INFO)
941 HandleInfoScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
942 else if (game_status == GAME_MODE_SCORES)
943 HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
948 GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500);
952 setup.sp_show_border_elements = !setup.sp_show_border_elements;
953 printf("Supaplex border elements %s\n",
954 setup.sp_show_border_elements ? "enabled" : "disabled");
963 case GAME_MODE_EDITOR:
964 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
965 HandleLevelEditorKeyInput(key);
968 case GAME_MODE_PLAYING:
973 RequestQuitGame(setup.ask_on_escape);
991 if (GameFrameDelay == 500)
992 GameFrameDelay = GAME_FRAME_DELAY;
994 GameFrameDelay = 500;
997 GameFrameDelay = (key - KSYM_0) * 10;
998 printf("Game speed == %d%% (%d ms delay between two frames)\n",
999 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
1005 options.debug = FALSE;
1006 printf("debug mode disabled\n");
1010 options.debug = TRUE;
1011 printf("debug mode enabled\n");
1016 if (!global.fps_slowdown)
1018 global.fps_slowdown = TRUE;
1019 global.fps_slowdown_factor = 2;
1020 printf("fps slowdown enabled -- display only every 2nd frame\n");
1022 else if (global.fps_slowdown_factor == 2)
1024 global.fps_slowdown_factor = 4;
1025 printf("fps slowdown enabled -- display only every 4th frame\n");
1029 global.fps_slowdown = FALSE;
1030 global.fps_slowdown_factor = 1;
1031 printf("fps slowdown disabled\n");
1036 ScrollStepSize = TILEX / 8;
1037 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
1041 ScrollStepSize = TILEX / 4;
1042 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
1046 ScrollStepSize = TILEX / 2;
1047 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
1051 ScrollStepSize = TILEX;
1052 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
1056 printf("::: currently using game engine version %d\n",
1057 game.engine_version);
1068 if (key == KSYM_Escape)
1070 game_status = GAME_MODE_MAIN;
1078 void HandleNoEvent()
1080 if (button_status && game_status != GAME_MODE_PLAYING)
1082 HandleButton(0, 0, -button_status, button_status);
1087 #if defined(NETWORK_AVALIABLE)
1088 if (options.network)
1095 static int HandleJoystickForAllPlayers()
1100 for (i = 0; i < MAX_PLAYERS; i++)
1102 byte joy_action = 0;
1105 if (!setup.input[i].use_joystick)
1109 joy_action = Joystick(i);
1110 result |= joy_action;
1112 if (!setup.input[i].use_joystick)
1115 stored_player[i].action = joy_action;
1121 void HandleJoystick()
1123 int joystick = HandleJoystickForAllPlayers();
1124 int keyboard = key_joystick_mapping;
1125 int joy = (joystick | keyboard);
1126 int left = joy & JOY_LEFT;
1127 int right = joy & JOY_RIGHT;
1128 int up = joy & JOY_UP;
1129 int down = joy & JOY_DOWN;
1130 int button = joy & JOY_BUTTON;
1131 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1132 int dx = (left ? -1 : right ? 1 : 0);
1133 int dy = (up ? -1 : down ? 1 : 0);
1135 switch (game_status)
1137 case GAME_MODE_TITLE:
1138 case GAME_MODE_MAIN:
1139 case GAME_MODE_LEVELS:
1140 case GAME_MODE_LEVELNR:
1141 case GAME_MODE_SETUP:
1142 case GAME_MODE_INFO:
1144 static unsigned int joystickmove_delay = 0;
1146 if (joystick && !button &&
1147 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1148 newbutton = dx = dy = 0;
1150 if (game_status == GAME_MODE_TITLE)
1151 HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1152 else if (game_status == GAME_MODE_MAIN)
1153 HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1154 else if (game_status == GAME_MODE_LEVELS)
1155 HandleChooseLevelSet(0,0,dx,dy,newbutton?MB_MENU_CHOICE : MB_MENU_MARK);
1156 else if (game_status == GAME_MODE_LEVELNR)
1157 HandleChooseLevelNr(0,0,dx,dy,newbutton? MB_MENU_CHOICE : MB_MENU_MARK);
1158 else if (game_status == GAME_MODE_SETUP)
1159 HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1160 else if (game_status == GAME_MODE_INFO)
1161 HandleInfoScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1165 case GAME_MODE_SCORES:
1166 HandleHallOfFame(0, 0, dx, dy, !newbutton);
1169 case GAME_MODE_EDITOR:
1170 HandleLevelEditorIdle();
1173 case GAME_MODE_PLAYING:
1174 if (tape.playing || keyboard)
1175 newbutton = ((joy & JOY_BUTTON) != 0);
1178 if (local_player->LevelSolved_GameEnd && newbutton)
1180 if (AllPlayersGone && newbutton)