#303: Typo fixes from mathnerd314
[supertux.git] / src / control / joystickkeyboardcontroller.cpp
index a3bcb83..3a0b7da 100644 (file)
 #include "console.hpp"
 #include "gameconfig.hpp"
 
+namespace{
+  const int SCAN_JOYSTICKS = Controller::CONTROLCOUNT + 1;
+}
+
 class JoystickKeyboardController::JoystickMenu : public Menu
 {
 public:
@@ -42,6 +46,8 @@ public:
   void update_menu_item(Control id);
   virtual void menu_action(MenuItem* item);
   JoystickKeyboardController* controller;
+private:
+  void recreateMenu();
 };
 
 class JoystickKeyboardController::KeyboardMenu : public Menu
@@ -62,101 +68,57 @@ JoystickKeyboardController::JoystickKeyboardController()
     key_options_menu(0), joystick_options_menu(0)
 {
   // initialize default keyboard map
-  keymap.insert(std::make_pair(SDLK_LEFT,     LEFT));
-  keymap.insert(std::make_pair(SDLK_RIGHT,    RIGHT));
-  keymap.insert(std::make_pair(SDLK_UP,       UP));
-  keymap.insert(std::make_pair(SDLK_DOWN,     DOWN));
-  keymap.insert(std::make_pair(SDLK_SPACE,    JUMP));
-  keymap.insert(std::make_pair(SDLK_LCTRL,    ACTION));
-  keymap.insert(std::make_pair(SDLK_LALT,     ACTION));
-  keymap.insert(std::make_pair(SDLK_ESCAPE,   PAUSE_MENU));
-  keymap.insert(std::make_pair(SDLK_p,        PAUSE_MENU));
-  keymap.insert(std::make_pair(SDLK_PAUSE,    PAUSE_MENU));
-  keymap.insert(std::make_pair(SDLK_RETURN,   MENU_SELECT));
-  keymap.insert(std::make_pair(SDLK_KP_ENTER, MENU_SELECT));
-  keymap.insert(std::make_pair(SDLK_CARET,    CONSOLE));
-  keymap.insert(std::make_pair(SDLK_DELETE,   PEEK_LEFT));
-  keymap.insert(std::make_pair(SDLK_END,      PEEK_RIGHT));
-
-  int joystick_count = SDL_NumJoysticks();
-  min_joybuttons = -1;
-  max_joybuttons = -1;
-  max_joyaxis    = -1;
-  max_joyhats    = -1;
-
-  for(int i = 0; i < joystick_count; ++i) {
-    SDL_Joystick* joystick = SDL_JoystickOpen(i);
-    bool good = true;
-    if(SDL_JoystickNumButtons(joystick) < 2) {
-      log_info << "Joystick " << i << " has less than 2 buttons" << std::endl;
-      good = false;
-    }
-    if(SDL_JoystickNumAxes(joystick) < 2
-       && SDL_JoystickNumHats(joystick) == 0) {
-      log_info << "Joystick " << i << " has less than 2 axes and no hat" << std::endl;
-      good = false;
-    }
-    if(!good) {
-      SDL_JoystickClose(joystick);
-      continue;
-    }
-
-    if(min_joybuttons < 0 || SDL_JoystickNumButtons(joystick) < min_joybuttons)
-      min_joybuttons = SDL_JoystickNumButtons(joystick);
-
-    if(SDL_JoystickNumButtons(joystick) > max_joybuttons)
-      max_joybuttons = SDL_JoystickNumButtons(joystick);
-
-    if(SDL_JoystickNumAxes(joystick) > max_joyaxis)
-      max_joyaxis = SDL_JoystickNumAxes(joystick);
-
-    if(SDL_JoystickNumHats(joystick) > max_joyhats)
-      max_joyhats = SDL_JoystickNumHats(joystick);
-
-    joysticks.push_back(joystick);
-  }
+  keymap[SDLK_LEFT]     = LEFT;
+  keymap[SDLK_RIGHT]    = RIGHT;
+  keymap[SDLK_UP]       = UP;
+  keymap[SDLK_DOWN]     = DOWN;
+  keymap[SDLK_SPACE]    = JUMP;
+  keymap[SDLK_LCTRL]    = ACTION;
+  keymap[SDLK_LALT]     = ACTION;
+  keymap[SDLK_ESCAPE]   = PAUSE_MENU;
+  keymap[SDLK_p]        = PAUSE_MENU;
+  keymap[SDLK_PAUSE]    = PAUSE_MENU;
+  keymap[SDLK_RETURN]   = MENU_SELECT;
+  keymap[SDLK_KP_ENTER] = MENU_SELECT;
+  keymap[SDLK_CARET]    = CONSOLE;
+  keymap[SDLK_DELETE]   = PEEK_LEFT;
+  keymap[SDLK_PAGEDOWN] = PEEK_RIGHT;
+  keymap[SDLK_HOME]     = PEEK_UP;
+  keymap[SDLK_END]      = PEEK_DOWN;
+
+  jump_with_up_joy = false;
+  jump_with_up_kbd = false;
+
+  updateAvailableJoysticks();
 
   dead_zone = 1000;
 
   // Default joystick button configuration
-  joy_button_map.insert(std::make_pair(0, JUMP));
-  joy_button_map.insert(std::make_pair(1, ACTION));
+  joy_button_map[0] = JUMP;
+  joy_button_map[1] = ACTION;
   // 6 or more Buttons
   if( min_joybuttons > 5 ){
-    joy_button_map.insert(std::make_pair( 4, PEEK_LEFT));
-    joy_button_map.insert(std::make_pair( 5, PEEK_RIGHT));
+    joy_button_map[4] = PEEK_LEFT;
+    joy_button_map[5] = PEEK_RIGHT;
     // 8 or more
     if(min_joybuttons > 7)
-      joy_button_map.insert(std::make_pair(min_joybuttons-1, PAUSE_MENU));
-    // map all remaining joystick buttons to MENU_SELECT
-    for(int i = 2; i < max_joybuttons; ++i) {
-      if( i != min_joybuttons-1 && i !=4  && i!= 5 )
-        joy_button_map.insert(std::make_pair(i, MENU_SELECT));
-    }
-
+      joy_button_map[min_joybuttons-1] = PAUSE_MENU;
   } else {
     // map the last 2 buttons to menu and pause
     if(min_joybuttons > 2)
-      joy_button_map.insert(std::make_pair(min_joybuttons-1, PAUSE_MENU));
+      joy_button_map[min_joybuttons-1] = PAUSE_MENU;
     // map all remaining joystick buttons to MENU_SELECT
     for(int i = 2; i < max_joybuttons; ++i) {
       if(i != min_joybuttons-1)
-        joy_button_map.insert(std::make_pair(i, MENU_SELECT));
+        joy_button_map[i] = MENU_SELECT;
     }
   }
 
   // Default joystick axis configuration
-  joy_axis_map.insert(std::make_pair(-1, LEFT));
-  joy_axis_map.insert(std::make_pair( 1, RIGHT));
-  joy_axis_map.insert(std::make_pair(-2, UP));
-  joy_axis_map.insert(std::make_pair( 2, DOWN));
-
-  // some joysticks or SDL seem to produce some bogus events after being opened
-  Uint32 ticks = SDL_GetTicks();
-  while(SDL_GetTicks() - ticks < 200) {
-    SDL_Event event;
-    SDL_PollEvent(&event);
-  }
+  joy_axis_map[-1] = LEFT;
+  joy_axis_map[ 1] = RIGHT;
+  joy_axis_map[-2] = UP;
+  joy_axis_map[ 2] = DOWN;
 }
 
 JoystickKeyboardController::~JoystickKeyboardController()
@@ -172,11 +134,73 @@ JoystickKeyboardController::~JoystickKeyboardController()
 }
 
 void
+JoystickKeyboardController::updateAvailableJoysticks()
+{
+  for(std::vector<SDL_Joystick*>::iterator i = joysticks.begin();
+      i != joysticks.end(); ++i) {
+    if(*i != 0)
+      SDL_JoystickClose(*i);
+  }
+  joysticks.clear();
+  
+  SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+
+  int joystick_count = SDL_NumJoysticks();
+  min_joybuttons = -1;
+  max_joybuttons = -1;
+  max_joyaxis    = -1;
+  max_joyhats    = -1;
+
+  if( joystick_count > 0 ){
+    for(int i = 0; i < joystick_count; ++i) {
+      SDL_Joystick* joystick = SDL_JoystickOpen(i);
+      bool good = true;
+      if(SDL_JoystickNumButtons(joystick) < 2) {
+        log_info << "Joystick " << i << ": " << SDL_JoystickName(i) << " has less than 2 buttons" << std::endl;
+        good = false;
+      }
+      if(SDL_JoystickNumAxes(joystick) < 2
+         && SDL_JoystickNumHats(joystick) == 0) {
+        log_info << "Joystick " << i << ": " << SDL_JoystickName(i) << " has less than 2 axes and no hat" << std::endl;
+        good = false;
+      }
+      if(!good) {
+        SDL_JoystickClose(joystick);
+        continue;
+      }
+
+      if(min_joybuttons < 0 || SDL_JoystickNumButtons(joystick) < min_joybuttons)
+        min_joybuttons = SDL_JoystickNumButtons(joystick);
+
+      if(SDL_JoystickNumButtons(joystick) > max_joybuttons)
+        max_joybuttons = SDL_JoystickNumButtons(joystick);
+
+      if(SDL_JoystickNumAxes(joystick) > max_joyaxis)
+        max_joyaxis = SDL_JoystickNumAxes(joystick);
+
+      if(SDL_JoystickNumHats(joystick) > max_joyhats)
+        max_joyhats = SDL_JoystickNumHats(joystick);
+
+      joysticks.push_back(joystick);
+    }
+  }
+
+  // some joysticks or SDL seem to produce some bogus events after being opened
+  Uint32 ticks = SDL_GetTicks();
+  while(SDL_GetTicks() - ticks < 200) {
+    SDL_Event event;
+    SDL_PollEvent(&event);
+  }
+}
+
+void
 JoystickKeyboardController::read(const lisp::Lisp& lisp)
 {
   const lisp::Lisp* keymap_lisp = lisp.get_lisp("keymap");
   if(keymap_lisp) {
     keymap.clear();
+    keymap_lisp->get("jump-with-up", jump_with_up_kbd);
     lisp::ListIterator iter(keymap_lisp);
     while(iter.next()) {
       if(iter.item() == "map") {
@@ -199,16 +223,15 @@ JoystickKeyboardController::read(const lisp::Lisp& lisp)
           log_info << "Invalid control '" << control << "' in keymap" << std::endl;
           continue;
         }
-        keymap.insert(std::make_pair((SDLKey) key, (Control) i));
-      } else {
-        log_info << "Invalid lisp element '" << iter.item() << "' in keymap" << std::endl;
+        keymap[(SDLKey) key] = (Control)i;
       }
     }
   }
 
   const lisp::Lisp* joystick_lisp = lisp.get_lisp("joystick");
   if(joystick_lisp) {
-    joystick_lisp->get("dead_zone", dead_zone);
+    joystick_lisp->get("dead-zone", dead_zone);
+    joystick_lisp->get("jump-with-up", jump_with_up_joy);
     lisp::ListIterator iter(joystick_lisp);
     while(iter.next()) {
       if(iter.item() == "map") {
@@ -234,7 +257,7 @@ JoystickKeyboardController::read(const lisp::Lisp& lisp)
             log_info << "Invalid button '" << button << "' in buttonmap" << std::endl;
             continue;
           }
-          reset_joybutton(button, (Control) i);
+          bind_joybutton(button, (Control) i);
         }
 
         if (map->get("axis",   axis)) {
@@ -242,7 +265,7 @@ JoystickKeyboardController::read(const lisp::Lisp& lisp)
             log_info << "Invalid axis '" << axis << "' in axismap" << std::endl;
             continue;
           }
-          reset_joyaxis(axis, (Control) i);
+          bind_joyaxis(axis, (Control) i);
         }
 
         if (map->get("hat",   hat)) {
@@ -253,7 +276,7 @@ JoystickKeyboardController::read(const lisp::Lisp& lisp)
             log_info << "Invalid axis '" << axis << "' in axismap" << std::endl;
             continue;
           } else {
-            reset_joyhat(hat, (Control) i);
+            bind_joyhat(hat, (Control) i);
           }
         }
       }
@@ -265,6 +288,7 @@ void
 JoystickKeyboardController::write(lisp::Writer& writer)
 {
   writer.start_list("keymap");
+  writer.write_bool("jump-with-up", jump_with_up_kbd);
   for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
     writer.start_list("map");
     writer.write_int("key", (int) i->first);
@@ -274,7 +298,8 @@ JoystickKeyboardController::write(lisp::Writer& writer)
   writer.end_list("keymap");
 
   writer.start_list("joystick");
-  writer.write_int("dead_zone", dead_zone);
+  writer.write_int("dead-zone", dead_zone);
+  writer.write_bool("jump-with-up", jump_with_up_joy);
 
   for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end();
       ++i) {
@@ -308,6 +333,15 @@ JoystickKeyboardController::reset()
 }
 
 void
+JoystickKeyboardController::set_joy_controls(Control id, bool value)
+{
+  if (jump_with_up_joy && id == Controller::UP)
+    controls[Controller::JUMP] = value;
+
+  controls[(Control)id] = value;
+}
+
+void
 JoystickKeyboardController::process_event(const SDL_Event& event)
 {
   switch(event.type) {
@@ -326,28 +360,8 @@ JoystickKeyboardController::process_event(const SDL_Event& event)
 
     case SDL_JOYBUTTONDOWN:
     case SDL_JOYBUTTONUP:
-      {
-        if(wait_for_joystick >= 0) {
-          if(event.type == SDL_JOYBUTTONUP)
-            return;
-
-          Control c = (Control) wait_for_joystick;
-          reset_joybutton(event.jbutton.button, c);
-          reset();
-          joystick_options_menu->update();
-          wait_for_joystick = -1;
-          return;
-        }
-
-        ButtonMap::iterator i = joy_button_map.find(event.jbutton.button);
-        if(i == joy_button_map.end()) {
-          log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl;
-          return;
-        }
-
-        controls[i->second] = (event.type == SDL_JOYBUTTONDOWN);
-        break;
-      }
+      process_button_event(event.jbutton);
+      break;
 
     default:
       break;
@@ -355,50 +369,73 @@ JoystickKeyboardController::process_event(const SDL_Event& event)
 }
 
 void
-JoystickKeyboardController::process_axis_event(const SDL_JoyAxisEvent& jaxis)
+JoystickKeyboardController::process_button_event(const SDL_JoyButtonEvent& jbutton)
 {
-  if (wait_for_joystick >= 0)
+  if(wait_for_joystick >= 0) 
     {
-      if (abs(jaxis.value) > dead_zone)
+      if(jbutton.state == SDL_PRESSED)
         {
-          if (jaxis.value < 0)
-            reset_joyaxis(-(jaxis.axis + 1), Control(wait_for_joystick));
-          else
-            reset_joyaxis(jaxis.axis + 1, Control(wait_for_joystick));
-
+          bind_joybutton(jbutton.button, (Control)wait_for_joystick);
           joystick_options_menu->update();
+          reset();
           wait_for_joystick = -1;
         }
+    } 
+  else 
+    {
+      ButtonMap::iterator i = joy_button_map.find(jbutton.button);
+      if(i == joy_button_map.end()) {
+        log_debug << "Unmapped joybutton " << (int)jbutton.button << " pressed" << std::endl;
+      } else {
+        set_joy_controls(i->second, (jbutton.state == SDL_PRESSED));
+      }
+    }
+}
+
+void
+JoystickKeyboardController::process_axis_event(const SDL_JoyAxisEvent& jaxis)
+{
+  if (wait_for_joystick >= 0)
+    {
+      if (abs(jaxis.value) > dead_zone) {
+        if (jaxis.value < 0)
+          bind_joyaxis(-(jaxis.axis + 1), Control(wait_for_joystick));
+        else
+          bind_joyaxis(jaxis.axis + 1, Control(wait_for_joystick));
+
+        joystick_options_menu->update();
+        wait_for_joystick = -1;
+      }
     }
   else
     {
       // Split the axis into left and right, so that both can be
-      // mapped seperatly (needed for jump/down vs up/down)
+      // mapped separately (needed for jump/down vs up/down)
       int axis = jaxis.axis + 1;
-          
+
       AxisMap::iterator left  = joy_axis_map.find(-axis);
       AxisMap::iterator right = joy_axis_map.find(axis);
 
       if(left == joy_axis_map.end()) {
         std::cout << "Unmapped joyaxis " << (int)jaxis.axis << " moved" << std::endl;
-      } else {         
+      } else {
         if (jaxis.value < -dead_zone)
-          controls[left->second]  = true;
+          set_joy_controls(left->second,  true);
         else if (jaxis.value > dead_zone)
-          controls[left->second]  = false;
+          set_joy_controls(left->second, false);
         else
-          controls[left->second]  = false;
+          set_joy_controls(left->second, false);
       }
 
       if(right == joy_axis_map.end()) {
         std::cout << "Unmapped joyaxis " << (int)jaxis.axis << " moved" << std::endl;
       } else {
         if (jaxis.value < -dead_zone)
-          controls[right->second] = false;            
+          set_joy_controls(right->second, false);
         else if (jaxis.value > dead_zone)
-          controls[right->second] = true;              
+          set_joy_controls(right->second, true);
         else
-          controls[right->second] = false;
+          set_joy_controls(right->second, false);
       }
     }
 }
@@ -407,20 +444,20 @@ void
 JoystickKeyboardController::process_hat_event(const SDL_JoyHatEvent& jhat)
 {
   Uint8 changed = hat_state ^ jhat.value;
-  
+
   if (wait_for_joystick >= 0)
     {
       if (changed & SDL_HAT_UP && jhat.value & SDL_HAT_UP)
-        reset_joyhat(SDL_HAT_UP, (Control)wait_for_joystick);
+        bind_joyhat(SDL_HAT_UP, (Control)wait_for_joystick);
 
       if (changed & SDL_HAT_DOWN && jhat.value & SDL_HAT_DOWN)
-        reset_joyhat(SDL_HAT_DOWN, (Control)wait_for_joystick);
+        bind_joyhat(SDL_HAT_DOWN, (Control)wait_for_joystick);
 
       if (changed & SDL_HAT_LEFT && jhat.value & SDL_HAT_LEFT)
-        reset_joyhat(SDL_HAT_LEFT, (Control)wait_for_joystick);
+        bind_joyhat(SDL_HAT_LEFT, (Control)wait_for_joystick);
 
       if (changed & SDL_HAT_RIGHT && jhat.value & SDL_HAT_RIGHT)
-        reset_joyhat(SDL_HAT_RIGHT, (Control)wait_for_joystick);
+        bind_joyhat(SDL_HAT_RIGHT, (Control)wait_for_joystick);
 
       joystick_options_menu->update();
       wait_for_joystick = -1;
@@ -431,28 +468,28 @@ JoystickKeyboardController::process_hat_event(const SDL_JoyHatEvent& jhat)
         {
           HatMap::iterator it = joy_hat_map.find(SDL_HAT_UP);
           if (it != joy_hat_map.end())
-            controls[it->second] = jhat.value & SDL_HAT_UP;
+            set_joy_controls(it->second, jhat.value & SDL_HAT_UP);
         }
-        
+
       if (changed & SDL_HAT_DOWN)
         {
           HatMap::iterator it = joy_hat_map.find(SDL_HAT_DOWN);
           if (it != joy_hat_map.end())
-            controls[it->second] = jhat.value & SDL_HAT_DOWN;          
+            set_joy_controls(it->second, jhat.value & SDL_HAT_DOWN);
         }
-        
+
       if (changed & SDL_HAT_LEFT)
         {
           HatMap::iterator it = joy_hat_map.find(SDL_HAT_LEFT);
           if (it != joy_hat_map.end())
-            controls[it->second] = jhat.value & SDL_HAT_LEFT;
+            set_joy_controls(it->second, jhat.value & SDL_HAT_LEFT);
         }
-        
+
       if (changed & SDL_HAT_RIGHT)
         {
           HatMap::iterator it = joy_hat_map.find(SDL_HAT_RIGHT);
           if (it != joy_hat_map.end())
-            controls[it->second] = jhat.value & SDL_HAT_RIGHT;          
+            set_joy_controls(it->second, jhat.value & SDL_HAT_RIGHT);
         }
     }
 
@@ -466,30 +503,26 @@ JoystickKeyboardController::process_key_event(const SDL_Event& event)
 
   // if console key was pressed: toggle console
   if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) {
-    if (event.type != SDL_KEYDOWN) return;
-    Console::instance->toggle();
-    return;
-  }
-
-  // if console is open: send key there
-  if (Console::instance->hasFocus()) {
-    process_console_key_event(event);
-    return;
-  }
-
-  // if menu mode: send key there
-  if (Menu::current()) {
-    process_menu_key_event(event);
-    return;
-  }
-
-  // default action: update controls
-  if(key_mapping == keymap.end()) {
-    log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl;
-    return;
+    if (event.type == SDL_KEYDOWN) 
+      Console::instance->toggle();
+  } else {
+    if (Console::instance->hasFocus()) {
+      // if console is open: send key there
+      process_console_key_event(event);
+    } else if (Menu::current()) {
+      // if menu mode: send key there
+      process_menu_key_event(event);
+    } else if(key_mapping == keymap.end()) {
+      // default action: update controls
+      //log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl;
+    } else {
+      Control control = key_mapping->second;
+      controls[control] = (event.type == SDL_KEYDOWN);
+      if (jump_with_up_kbd && control == UP){
+        controls[JUMP] = (event.type == SDL_KEYDOWN);
+      }
+    }
   }
-  Control control = key_mapping->second;
-  controls[control] = (event.type == SDL_KEYDOWN);
 }
 
 void
@@ -550,7 +583,7 @@ JoystickKeyboardController::process_menu_key_event(const SDL_Event& event)
 
     if(event.key.keysym.sym != SDLK_ESCAPE
         && event.key.keysym.sym != SDLK_PAUSE) {
-      reset_key(event.key.keysym.sym, (Control) wait_for_key);
+      bind_key(event.key.keysym.sym, (Control) wait_for_key);
     }
     reset();
     key_options_menu->update();
@@ -600,90 +633,66 @@ JoystickKeyboardController::process_menu_key_event(const SDL_Event& event)
   controls[control] = (event.type == SDL_KEYDOWN);
 }
 
-void 
-JoystickKeyboardController::unbind_control(Control control)
+void
+JoystickKeyboardController::unbind_joystick_control(Control control)
 {
   // remove all previous mappings for that control
-  for(AxisMap::iterator i = joy_axis_map.begin(); 
-      i != joy_axis_map.end(); /* no ++i */) {
-    if(i->second == control) {
-      AxisMap::iterator e = i;
-      ++i;
-      joy_axis_map.erase(e);
-    } else {
+  for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); /* no ++i */) {
+    if(i->second == control)
+      joy_axis_map.erase(i++);
+    else
       ++i;
-    }
   }
 
-  for(ButtonMap::iterator i = joy_button_map.begin();
-      i != joy_button_map.end(); /* no ++i */) {
-    if(i->second == control) {
-      ButtonMap::iterator e = i;
-      ++i;
-      joy_button_map.erase(e);
-    } else {
+  for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end(); /* no ++i */) {
+    if(i->second == control)
+      joy_button_map.erase(i++);
+    else
       ++i;
-    }
   }
 
-  for(HatMap::iterator i = joy_hat_map.begin();
-      i != joy_hat_map.end(); /* no ++i */) {
-    if(i->second == control) {
-      HatMap::iterator e = i;
-      ++i;
-      joy_hat_map.erase(e);
-    } else {
+  for(HatMap::iterator i = joy_hat_map.begin();  i != joy_hat_map.end(); /* no ++i */) {
+    if(i->second == control)
+      joy_hat_map.erase(i++);
+    else
       ++i;
-    }
   }
 }
 
 void
-JoystickKeyboardController::reset_joyaxis(int axis, Control control)
+JoystickKeyboardController::bind_joyaxis(int axis, Control control)
 {
   // axis isn't the SDL axis number, but axisnumber + 1 with sign
   // changed depending on if the positive or negative end is to be
   // used (negative axis 0 becomes -1, positive axis 2 becomes +3,
   // etc.)
 
-  unbind_control(control);
-
-  // remove all previous and for that axis
-  AxisMap::iterator i = joy_axis_map.find(axis);
-  if(i != joy_axis_map.end())
-    joy_axis_map.erase(i);
+  unbind_joystick_control(control);
 
   // add new mapping
-  joy_axis_map.insert(std::make_pair(axis, control));
+  joy_axis_map[axis] = control;
 }
 
 void
-JoystickKeyboardController::reset_joyhat(int dir, Control c)
+JoystickKeyboardController::bind_joyhat(int dir, Control c)
 {
-  unbind_control(c);
-  joy_hat_map.insert(std::make_pair(dir, c));
+  unbind_joystick_control(c);
+
+  // add new mapping
+  joy_hat_map[dir] = c;
 }
 
 void
-JoystickKeyboardController::reset_joybutton(int button, Control control)
+JoystickKeyboardController::bind_joybutton(int button, Control control)
 {
-  unbind_control(control);
+  unbind_joystick_control(control);
 
   // add new mapping
-  joy_button_map.insert(std::make_pair(button, control));
-
-  // map all unused buttons to MENU_SELECT
-  for(int b = 0; b < max_joybuttons; ++b) {
-    ButtonMap::iterator i = joy_button_map.find(b);
-    if(i != joy_button_map.end())
-      continue;
-
-    joy_button_map.insert(std::make_pair(b, MENU_SELECT));
-  }
+  joy_button_map[button] = control;
 }
 
 void
-JoystickKeyboardController::reset_key(SDLKey key, Control control)
+JoystickKeyboardController::bind_key(SDLKey key, Control control)
 {
   // remove all previous mappings for that control and for that key
   for(KeyMap::iterator i = keymap.begin();
@@ -696,12 +705,32 @@ JoystickKeyboardController::reset_key(SDLKey key, Control control)
       ++i;
     }
   }
+
   KeyMap::iterator i = keymap.find(key);
   if(i != keymap.end())
     keymap.erase(i);
 
   // add new mapping
-  keymap.insert(std::make_pair(key, control));
+  keymap[key]= control;
+}
+
+void
+JoystickKeyboardController::print_joystick_mappings()
+{
+  std::cout << "Joystick Mappings" << std::endl;
+  std::cout << "-----------------" << std::endl;
+  for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); ++i) {
+    std::cout << "Axis: " << i->first << " -> " << i->second << std::endl;
+  }
+
+  for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end(); ++i) {
+    std::cout << "Button: " << i->first << " -> " << i->second << std::endl;
+  }
+
+  for(HatMap::iterator i = joy_hat_map.begin(); i != joy_hat_map.end(); ++i) {
+    std::cout << "Hat: " << i->first << " -> " << i->second << std::endl;
+  }
+  std::cout << std::endl;
 }
 
 SDLKey
@@ -722,15 +751,14 @@ JoystickKeyboardController::reversemap_joyaxis(Control c)
     if(i->second == c)
       return i->first;
   }
-  
+
   return 0;
 }
 
 int
 JoystickKeyboardController::reversemap_joybutton(Control c)
 {
-  for(ButtonMap::iterator i = joy_button_map.begin();
-      i != joy_button_map.end(); ++i) {
+  for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end(); ++i) {
     if(i->second == c)
       return i->first;
   }
@@ -741,13 +769,12 @@ JoystickKeyboardController::reversemap_joybutton(Control c)
 int
 JoystickKeyboardController::reversemap_joyhat(Control c)
 {
-  for(HatMap::iterator i = joy_hat_map.begin();
-      i != joy_hat_map.end(); ++i) {
+  for(HatMap::iterator i = joy_hat_map.begin(); i != joy_hat_map.end(); ++i) {
     if(i->second == c)
       return i->first;
   }
 
-  return -1; 
+  return -1;
 }
 
 Menu*
@@ -786,9 +813,12 @@ JoystickKeyboardController::KeyboardMenu::KeyboardMenu(
     add_controlfield(Controller::ACTION,     _("Action"));
     add_controlfield(Controller::PEEK_LEFT,  _("Peek Left"));
     add_controlfield(Controller::PEEK_RIGHT, _("Peek Right"));
+    add_controlfield(Controller::PEEK_UP,    _("Peek Up"));
+    add_controlfield(Controller::PEEK_DOWN,  _("Peek Down"));
     if (config->console_enabled) {
       add_controlfield(Controller::CONSOLE, _("Console"));
     }
+    add_toggle(Controller::CONTROLCOUNT, _("Jump with Up"), controller->jump_with_up_kbd);
     add_hl();
     add_back(_("Back"));
     update();
@@ -835,9 +865,12 @@ JoystickKeyboardController::KeyboardMenu::get_key_name(SDLKey key)
 void
 JoystickKeyboardController::KeyboardMenu::menu_action(MenuItem* item)
 {
-  assert(item->id >= 0 && item->id < Controller::CONTROLCOUNT);
-  item->change_input(_("Press Key"));
-  controller->wait_for_key = item->id;
+  if(item->id >= 0 && item->id < Controller::CONTROLCOUNT){
+    item->change_input(_("Press Key"));
+    controller->wait_for_key = item->id;
+  } else if( item->id == Controller::CONTROLCOUNT) {
+    controller->jump_with_up_kbd = item->toggled;
+  } 
 }
 
 void
@@ -860,10 +893,15 @@ JoystickKeyboardController::KeyboardMenu::update()
     controller->reversemap_key(Controller::PEEK_LEFT)));
   get_item_by_id((int) Controller::PEEK_RIGHT).change_input(get_key_name(
     controller->reversemap_key(Controller::PEEK_RIGHT)));
+  get_item_by_id((int) Controller::PEEK_UP).change_input(get_key_name(
+    controller->reversemap_key(Controller::PEEK_UP)));
+  get_item_by_id((int) Controller::PEEK_DOWN).change_input(get_key_name(
+    controller->reversemap_key(Controller::PEEK_DOWN)));
   if (config->console_enabled) {
     get_item_by_id((int) Controller::CONSOLE).change_input(get_key_name(
       controller->reversemap_key(Controller::CONSOLE)));
   }
+  get_item_by_id(Controller::CONTROLCOUNT).toggled = controller->jump_with_up_kbd;
 }
 
 //---------------------------------------------------------------------------
@@ -872,6 +910,16 @@ JoystickKeyboardController::JoystickMenu::JoystickMenu(
   JoystickKeyboardController* _controller)
   : controller(_controller)
 {
+  recreateMenu();
+}
+
+JoystickKeyboardController::JoystickMenu::~JoystickMenu()
+{}
+
+void
+JoystickKeyboardController::JoystickMenu::recreateMenu()
+{
+  clear();
   add_label(_("Setup Joystick"));
   add_hl();
   if(controller->joysticks.size() > 0) {
@@ -884,17 +932,28 @@ JoystickKeyboardController::JoystickMenu::JoystickMenu(
     add_controlfield(Controller::PAUSE_MENU,  _("Pause/Menu"));
     add_controlfield(Controller::PEEK_LEFT,   _("Peek Left"));
     add_controlfield(Controller::PEEK_RIGHT,  _("Peek Right"));
+    add_controlfield(Controller::PEEK_UP,     _("Peek Up"));
+    add_controlfield(Controller::PEEK_DOWN,   _("Peek Down"));
+
+    add_toggle(Controller::CONTROLCOUNT, _("Jump with Up"), controller->jump_with_up_joy);
   } else {
-    add_deactive(-1, _("No Joysticks found"));
+    add_inactive(-1, _("No Joysticks found"));
   }
+  add_inactive(-1,"");
+  add_entry(SCAN_JOYSTICKS, _("Scan for Joysticks"));
+
+  //Show Joysticks currently activated:
+  for(std::vector<SDL_Joystick*>::iterator i = controller->joysticks.begin();
+      i != controller->joysticks.end(); ++i) {
+    if(*i != 0)
+      add_inactive(-1, SDL_JoystickName(SDL_JoystickIndex(*i)) );
+  }
+
   add_hl();
   add_back(_("Back"));
   update();
 }
 
-JoystickKeyboardController::JoystickMenu::~JoystickMenu()
-{}
-
 std::string
 JoystickKeyboardController::JoystickMenu::get_button_name(int button)
 {
@@ -909,9 +968,15 @@ JoystickKeyboardController::JoystickMenu::get_button_name(int button)
 void
 JoystickKeyboardController::JoystickMenu::menu_action(MenuItem* item)
 {
-  assert(item->id >= 0 && item->id < Controller::CONTROLCOUNT);
-  item->change_input(_("Press Button"));
-  controller->wait_for_joystick = item->id;
+  if (item->id >= 0 && item->id < Controller::CONTROLCOUNT) {
+    item->change_input(_("Press Button"));
+    controller->wait_for_joystick = item->id;
+  } else if (item->id == Controller::CONTROLCOUNT) {
+    controller->jump_with_up_joy = item->toggled;
+  } else if( item->id == SCAN_JOYSTICKS) {
+    controller->updateAvailableJoysticks();
+    recreateMenu();
+  }
 }
 
 void
@@ -941,13 +1006,13 @@ JoystickKeyboardController::JoystickMenu::update_menu_item(Control id)
       name << "X2";
     else if (abs(axis) == 3)
       name << "Y2";
-    else 
+    else
       name << abs(axis);
 
     get_item_by_id((int)id).change_input(name.str());
   } else if (hat_dir != -1) {
     std::string name;
-    
+
     switch (hat_dir)
       {
         case SDL_HAT_UP:
@@ -993,4 +1058,8 @@ JoystickKeyboardController::JoystickMenu::update()
   update_menu_item(Controller::PAUSE_MENU);
   update_menu_item(Controller::PEEK_LEFT);
   update_menu_item(Controller::PEEK_RIGHT);
+  update_menu_item(Controller::PEEK_UP);
+  update_menu_item(Controller::PEEK_DOWN);
+
+  get_item_by_id(Controller::CONTROLCOUNT).toggled = controller->jump_with_up_joy;
 }