diff -r fca7ab11dba2 zap/Event.cpp
--- a/zap/Event.cpp	Fri Sep 02 22:46:59 2011 -0600
+++ b/zap/Event.cpp	Fri Sep 02 23:40:24 2011 -0600
@@ -112,27 +112,36 @@
       // If the current axes direction is set in the keyCodeDownDeltaMask, set the key down
       if (Joystick::JoystickInputData[i].axesMask & keyCodeDownDeltaMask)
       {
-         setKeyState(Joystick::JoystickInputData[i].keyCode, true);
-
-         if(UserInterface::current)
-            UserInterface::current->onKeyDown(Joystick::JoystickInputData[i].keyCode, 0);
-
+         keyCodeDown(Joystick::JoystickInputData[i].keyCode, 0);
          continue;
       }
 
       // If the current axes direction is set in the keyCodeUpDeltaMask, set the key up
       if (Joystick::JoystickInputData[i].axesMask & keyCodeUpDeltaMask)
-      {
-         setKeyState(Joystick::JoystickInputData[i].keyCode, false);
-
-         if(UserInterface::current)
-            UserInterface::current->onKeyUp(Joystick::JoystickInputData[i].keyCode);
-      }
+         keyCodeUp(Joystick::JoystickInputData[i].keyCode);
    }
 
 
    // Finally alter the global axes KeyCode mask to reflect the current keyState
-      Joystick::AxesKeyCodeMask = currentKeyCodeMask;
+   Joystick::AxesKeyCodeMask = currentKeyCodeMask;
+}
+
+
+void Event::keyCodeUp(KeyCode keyCode)
+{
+   setKeyState(keyCode, false);
+
+   if(UserInterface::current)
+      UserInterface::current->onKeyUp(keyCode);
+}
+
+
+void Event::keyCodeDown(KeyCode keyCode, char ascii)
+{
+   setKeyState(keyCode, true);
+
+   if(UserInterface::current)
+      UserInterface::current->onKeyDown(keyCode, ascii);
 }
 
 
@@ -191,10 +200,10 @@
          break;
 
          // TODO:  Do we need joyball and joyhat?
-//      case SDL_JOYBALLMOTION:
-//         onJoyBall(event->jball.which, event->jball.ball, event->jball.xrel, event->jball.yrel);
-//         break;
-//
+      case SDL_JOYBALLMOTION:
+         onJoyBall(event->jball.which, event->jball.ball, event->jball.xrel, event->jball.yrel);
+         break;
+
       case SDL_JOYHATMOTION:
          onJoyHat(event->jhat.which, event->jhat.hat, event->jhat.value);
          break;
@@ -284,21 +293,14 @@
    else
    {
       KeyCode keyCode = sdlKeyToKeyCode(key);
-      setKeyState(keyCode, true);
-
-      if(UserInterface::current)
-         UserInterface::current->onKeyDown(keyCode, keyToAscii(unicode, keyCode));
+      keyCodeDown(keyCode, keyToAscii(unicode, keyCode));
    }
 }
 
 
 void Event::onKeyUp(SDLKey key, SDLMod mod, U16 unicode)
 {
-   KeyCode keyCode = sdlKeyToKeyCode(key);
-   setKeyState(keyCode, false);
-
-   if(UserInterface::current)
-      UserInterface::current->onKeyUp(keyCode);
+   keyCodeUp(sdlKeyToKeyCode(key));
 }
 
 void Event::onMouseFocus()
@@ -329,29 +331,21 @@
 {
    setMousePos(x, y);
 
-   if(!UserInterface::current)
-      return;    // Bail if no current UI
-
-   setKeyState(keyCode, true);
-
-   UserInterface::current->onKeyDown(keyCode, 0);
+   keyCodeDown(keyCode, 0);
 }
 
 void Event::onMouseButtonUp(S32 x, S32 y, KeyCode keyCode)
 {
    setMousePos(x, y);
 
-   if(!UserInterface::current)
-      return;    // Bail if no current UI
-
-   setKeyState(keyCode, false);
-
-   UserInterface::current->onKeyUp(keyCode);
+   keyCodeUp(keyCode);
 }
 
 
 void Event::onJoyAxis(U8 whichJoystick, U8 axis, S16 value)
 {
+//   logprintf("SDL Axis number: %u, value: %d", axis, value);
+
    if(axis < Joystick::rawAxisCount)
       Joystick::rawAxis[axis] = (F32)value / (F32)S16_MAX;
 
@@ -391,39 +385,46 @@
 
 void Event::onJoyButtonDown(U8 which, U8 button)
 {
-   KeyCode keyCode = joyButtonToKeyCode(Joystick::remapJoystickButton(button));
-   setKeyState(keyCode, true);
-
-   if(UserInterface::current)
-      UserInterface::current->onKeyDown(keyCode, 0);
+   keyCodeDown(joyButtonToKeyCode(Joystick::remapJoystickButton(button)), 0);
 }
 
 void Event::onJoyButtonUp(U8 which, U8 button)
 {
-   KeyCode keyCode = joyButtonToKeyCode(Joystick::remapJoystickButton(button));
-   setKeyState(keyCode, false);
-
-   if(UserInterface::current)
-      UserInterface::current->onKeyUp(keyCode);
+   keyCodeUp(joyButtonToKeyCode(Joystick::remapJoystickButton(button)));
 }
 
-void Event::onJoyHat(U8 which, U8 hat, U8 value)
+
+extern KeyCode joyHatToKeyCode(int buttonIndex);
+
+// See SDL_Joystick.h for the SDL_HAT_* mask definitions
+void Event::onJoyHat(U8 which, U8 hat, U8 directionMask)
 {
-   printf("Hat: %i\n", value);
-   // Looks like it is using bitmask for value
-   // 1 = up
-   // 2 = right
-   // 4 = down
-   // 8 = left
-   // 3 = up + right
-   // 6 = down + right
-   // 12 = down + left
-   // 9 = up + left
+//   logprintf("SDL Hat number: %u, value: %u", hat, directionMask);
+
+   KeyCode keyCode;
+   U32 keyCodeDownDeltaMask = directionMask & ~Joystick::HatKeyCodeMask;
+   U32 keyCodeUpDeltaMask = ~directionMask & Joystick::HatKeyCodeMask;
+
+   for (S32 i = 0; i < MaxHatDirections; i++)
+   {
+      keyCode = joyHatToKeyCode(BIT(i));  // BIT(i) corresponds to a defined SDL_HAT_*  value
+
+      // If the current hat direction is set in the keyCodeDownDeltaMask, set the key down
+      if (keyCodeDownDeltaMask & BIT(i))
+         keyCodeDown(keyCode, 0);
+
+      // If the current hat direction is set in the keyCodeUpDeltaMask, set the key up
+      if (keyCodeUpDeltaMask & BIT(i))
+         keyCodeUp(keyCode);
+   }
+
+   // Finally alter the global hat KeyCode mask to reflect the current keyState
+   Joystick::HatKeyCodeMask = directionMask;
 }
 
 void Event::onJoyBall(U8 which, U8 ball, S16 xrel, S16 yrel)
 {
-
+//   logprintf("SDL Ball number: %u, relative x: %d, relative y: %d", ball, xrel, yrel);
 }
 
 void Event::onMinimize()
diff -r fca7ab11dba2 zap/Event.h
--- a/zap/Event.h	Fri Sep 02 22:46:59 2011 -0600
+++ b/zap/Event.h	Fri Sep 02 23:40:24 2011 -0600
@@ -21,6 +21,9 @@
    static void setMousePos(S32 x, S32 y);
    static void updateJoyAxesDirections(U32 axisMask, S16 value);
 
+   static void keyCodeUp(KeyCode keyCode);
+   static void keyCodeDown(KeyCode keyCode, char ascii);
+
 public:
    Event();
    virtual ~Event();
@@ -40,7 +43,7 @@
    static void onJoyAxis(U8 which, U8 axis, S16 value);
    static void onJoyButtonDown(U8 which, U8 button);
    static void onJoyButtonUp(U8 which, U8 button);
-   static void onJoyHat(U8 which, U8 hat, U8 value);
+   static void onJoyHat(U8 which, U8 hat, U8 directionMask);
    static void onJoyBall(U8 which, U8 ball, S16 xrel, S16 yrel);
    static void onMinimize();
    static void onRestore();
diff -r fca7ab11dba2 zap/Joystick.cpp
--- a/zap/Joystick.cpp	Fri Sep 02 22:46:59 2011 -0600
+++ b/zap/Joystick.cpp	Fri Sep 02 23:40:24 2011 -0600
@@ -44,6 +44,7 @@
 S16 Joystick::SensitivityThreshold = 3200;  // out of 32767
 S32 Joystick::UseJoystickNumber = 0;
 U32 Joystick::AxesKeyCodeMask = 0;
+U32 Joystick::HatKeyCodeMask = 0;
 
 
 // Needs to be Aligned with JoystickAxesDirections
diff -r fca7ab11dba2 zap/Joystick.h
--- a/zap/Joystick.h	Fri Sep 02 22:46:59 2011 -0600
+++ b/zap/Joystick.h	Fri Sep 02 23:40:24 2011 -0600
@@ -110,6 +110,14 @@
    MaxAxesDirections
 };
 
+enum JoystickHatDirections {
+   HatUp,
+   HatRight,
+   HatDown,
+   HatLeft,
+   MaxHatDirections
+};
+
 enum AlignType {
    ALIGN_LEFT,
    ALIGN_CENTER,
@@ -154,6 +162,7 @@
    static JoystickInfo PredefinedJoystickList[ControllerTypeCount];
    static JoystickInput JoystickInputData[MaxAxesDirections];
    static U32 AxesKeyCodeMask;
+   static U32 HatKeyCodeMask;
 
    static bool initJoystick();
    static void shutdownJoystick();
diff -r fca7ab11dba2 zap/UIDiagnostics.cpp
--- a/zap/UIDiagnostics.cpp	Fri Sep 02 22:46:59 2011 -0600
+++ b/zap/UIDiagnostics.cpp	Fri Sep 02 23:40:24 2011 -0600
@@ -417,7 +417,7 @@
       hpos += drawStringAndGetWidthf( hpos, ypos, textsize - 2, "Raw Controller Input [%d]: ", Joystick::UseJoystickNumber);
 
       for(U32 i = 0; i < MaxControllerButtons; i++)
-         if(Joystick::ButtonMask & (1 << i))
+         if(Joystick::ButtonMask & BIT(i))
             hpos += drawStringAndGetWidthf( hpos, ypos, textsize - 2, "(%d)", i ) + 5;
 
       ypos += textsize + gap + 10;
diff -r fca7ab11dba2 zap/keyCode.cpp
--- a/zap/keyCode.cpp	Fri Sep 02 22:46:59 2011 -0600
+++ b/zap/keyCode.cpp	Fri Sep 02 23:40:24 2011 -0600
@@ -1076,6 +1076,7 @@
 }
 #endif
 
+
 KeyCode joyButtonToKeyCode(int buttonIndex)
 {
    switch(buttonIndex)
@@ -1100,14 +1101,24 @@
          return BUTTON_START;
       case 9:
          return BUTTON_BACK;
-      case 10:
+      default:
+         return BUTTON_UNKNOWN;
+   }
+}
+
+
+KeyCode joyHatToKeyCode(int hatDirectionMask)
+{
+   switch(hatDirectionMask)
+   {
+      case 1:
          return BUTTON_DPAD_UP;
-      case 11:
+      case 2:
+         return BUTTON_DPAD_RIGHT;
+      case 4:
          return BUTTON_DPAD_DOWN;
-      case 12:
+      case 8:
          return BUTTON_DPAD_LEFT;
-      case 13:
-         return BUTTON_DPAD_RIGHT;
       default:
          return BUTTON_UNKNOWN;
    }
