diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx
index 870d11cc7..53e53f898 100644
--- a/stella/src/emucore/EventHandler.cxx
+++ b/stella/src/emucore/EventHandler.cxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: EventHandler.cxx,v 1.138 2005-12-29 21:16:26 stephena Exp $
+// $Id: EventHandler.cxx,v 1.139 2006-01-04 01:24:17 stephena Exp $
 //============================================================================
 
 #include <sstream>
@@ -175,6 +175,8 @@ void EventHandler::reset(State state)
   setPaddleSpeed(1, myOSystem->settings().getInt("p2speed"));
   setPaddleSpeed(2, myOSystem->settings().getInt("p3speed"));
   setPaddleSpeed(3, myOSystem->settings().getInt("p4speed"));
+
+  myEventStreamer->reset();
 }
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/stella/src/emucore/EventStreamer.cxx b/stella/src/emucore/EventStreamer.cxx
index 23b2b4881..d354b5a11 100644
--- a/stella/src/emucore/EventStreamer.cxx
+++ b/stella/src/emucore/EventStreamer.cxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: EventStreamer.cxx,v 1.3 2005-12-29 21:16:28 stephena Exp $
+// $Id: EventStreamer.cxx,v 1.4 2006-01-04 01:24:17 stephena Exp $
 //============================================================================
 
 #include "bspf.hxx"
@@ -44,6 +44,16 @@ EventStreamer::~EventStreamer()
   myStreamWriter.close();
 }
 
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void EventStreamer::reset()
+{
+cerr << "EventStreamer::reset()\n";
+  myEventWriteFlag = false;
+  myEventReadFlag = false;
+  myFrameCounter = -1;
+  myEventPos = 0;
+}
+
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 bool EventStreamer::startRecording()
 {
@@ -57,10 +67,8 @@ bool EventStreamer::startRecording()
     return false;
   myEventHistory.clear();
 
-  myEventWriteFlag = true;
-  myEventReadFlag = false;
-
-  return myEventWriteFlag;
+  reset();
+  return myEventWriteFlag = true;
 }
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -97,6 +105,7 @@ bool EventStreamer::stopRecording()
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 bool EventStreamer::loadRecording()
 {
+cerr << "EventStreamer::loadRecording()\n";
   string eventfile = /*myOSystem->baseDir() + BSPF_PATH_SEPARATOR +*/ "test.inp";
   if(!myStreamReader.open(eventfile))
     return false;
@@ -128,10 +137,8 @@ bool EventStreamer::loadRecording()
     return false;
   }
 
-  myEventWriteFlag = false;
+  reset();
   myEventReadFlag  = myEventHistory.size() > 0;
-  myFrameCounter = -1;
-  myEventPos = 0;
 
   return true;
 }
diff --git a/stella/src/emucore/EventStreamer.hxx b/stella/src/emucore/EventStreamer.hxx
index 6fd9c6c1c..365fcb84e 100644
--- a/stella/src/emucore/EventStreamer.hxx
+++ b/stella/src/emucore/EventStreamer.hxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: EventStreamer.hxx,v 1.2 2005-12-29 01:25:07 stephena Exp $
+// $Id: EventStreamer.hxx,v 1.3 2006-01-04 01:24:17 stephena Exp $
 //============================================================================
 
 #ifndef EVENTSTREAMER_HXX
@@ -48,7 +48,7 @@ class OSystem;
   the correct order at the correct time.
 
   @author  Stephen Anthony
-  @version $Id: EventStreamer.hxx,v 1.2 2005-12-29 01:25:07 stephena Exp $
+  @version $Id: EventStreamer.hxx,v 1.3 2006-01-04 01:24:17 stephena Exp $
 */
 class EventStreamer
 {
@@ -99,6 +99,11 @@ class EventStreamer
     */
     void nextFrame();
 
+    /**
+      Reset to base state (not saving or loading an eventstream)
+    */
+    void reset();
+
   private:
 
   private:
diff --git a/stella/src/gui/CommandDialog.cxx b/stella/src/gui/CommandDialog.cxx
index 919d6e2d5..cc9833178 100644
--- a/stella/src/gui/CommandDialog.cxx
+++ b/stella/src/gui/CommandDialog.cxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: CommandDialog.cxx,v 1.5 2005-12-19 02:19:49 stephena Exp $
+// $Id: CommandDialog.cxx,v 1.6 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -26,35 +26,6 @@
 #include "CommandDialog.hxx"
 #include "EventHandler.hxx"
 
-enum {
-  kSelectCmd     = 'Csel',
-  kResetCmd      = 'Cres',
-  kColorCmd      = 'Ccol',
-  kBWCmd         = 'Cbwt',
-  kLeftDiffACmd  = 'Clda',
-  kLeftDiffBCmd  = 'Cldb',
-  kRightDiffACmd = 'Crda',
-  kRightDiffBCmd = 'Crdb',
-  kSaveStateCmd  = 'Csst',
-  kStateSlotCmd  = 'Ccst',
-  kLoadStateCmd  = 'Clst',
-  kSnapshotCmd   = 'Csnp',
-  kFormatCmd     = 'Cfmt',
-  kPaletteCmd    = 'Cpal',
-  kReloadRomCmd  = 'Crom',
-  kExitCmd       = 'Clex'
-};
-
-enum {
-  kUpArrow    = 256+17,
-  kDownArrow  = 256+18,
-  kLeftArrow  = 256+20,
-  kRightArrow = 256+19,
-
-  kNumRows = 4,
-  kNumCols = 4
-};
-
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 CommandDialog::CommandDialog(OSystem* osystem, DialogContainer* parent)
   : Dialog(osystem, parent, 0, 0, 16, 16),
@@ -180,7 +151,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
   // Only detect the cursor keys, otherwise pass to base class
   switch(ascii)
   {
-    case kUpArrow:
+    case kCursorUp:
       if (row > 0)
         --row;
       else if(col > 0)
@@ -190,7 +161,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
       }
       break;
 
-    case kDownArrow:
+    case kCursorDown:
       if (row < kNumRows - 1)
         ++row;
       else if(col < kNumCols - 1)
@@ -200,7 +171,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
       }
       break;
 
-    case kLeftArrow:
+    case kCursorLeft:
       if (col > 0)
         --col;
       else if(row > 0)
@@ -210,7 +181,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
       }
       break;
 
-    case kRightArrow:
+    case kCursorRight:
       if (col < kNumCols - 1)
         ++col;
       else if(row < kNumRows - 1)
@@ -245,16 +216,16 @@ void CommandDialog::handleJoyAxis(int stick, int axis, int value)
   if(axis % 2 == 0)  // x-direction
   {
     if(value < 0)
-      key = kLeftArrow;
+      key = kCursorLeft;
     else if(value > 0)
-      key = kRightArrow;
+      key = kCursorRight;
   }
   else   // y-direction
   {
     if(value < 0)
-      key = kUpArrow;
+      key = kCursorUp;
     else if(value > 0)
-      key = kDownArrow;
+      key = kCursorDown;
   }
 
   if(key != -1)
diff --git a/stella/src/gui/CommandDialog.hxx b/stella/src/gui/CommandDialog.hxx
index 783d213dd..b13bbb709 100644
--- a/stella/src/gui/CommandDialog.hxx
+++ b/stella/src/gui/CommandDialog.hxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: CommandDialog.hxx,v 1.3 2005-12-24 22:09:36 stephena Exp $
+// $Id: CommandDialog.hxx,v 1.4 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -44,6 +44,30 @@ class CommandDialog : public Dialog
 
   private:
     int mySelectedItem;
+
+    enum {
+      kSelectCmd     = 'Csel',
+      kResetCmd      = 'Cres',
+      kColorCmd      = 'Ccol',
+      kBWCmd         = 'Cbwt',
+      kLeftDiffACmd  = 'Clda',
+      kLeftDiffBCmd  = 'Cldb',
+      kRightDiffACmd = 'Crda',
+      kRightDiffBCmd = 'Crdb',
+      kSaveStateCmd  = 'Csst',
+      kStateSlotCmd  = 'Ccst',
+      kLoadStateCmd  = 'Clst',
+      kSnapshotCmd   = 'Csnp',
+      kFormatCmd     = 'Cfmt',
+      kPaletteCmd    = 'Cpal',
+      kReloadRomCmd  = 'Crom',
+      kExitCmd       = 'Clex'
+    };
+
+    enum {
+      kNumRows = 4,
+      kNumCols = 4
+    };
 };
 
 #endif
diff --git a/stella/src/gui/DialogContainer.cxx b/stella/src/gui/DialogContainer.cxx
index d9892db46..522b2dd13 100644
--- a/stella/src/gui/DialogContainer.cxx
+++ b/stella/src/gui/DialogContainer.cxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: DialogContainer.cxx,v 1.22 2005-12-24 22:50:53 stephena Exp $
+// $Id: DialogContainer.cxx,v 1.23 2006-01-04 01:24:17 stephena Exp $
 //============================================================================
 
 #include "OSystem.hxx"
@@ -72,6 +72,31 @@ void DialogContainer::updateTime(uInt32 time)
     myClickRepeatTime = myTime + kClickRepeatSustainDelay;
   }
 
+  if(myCurrentAxisDown.stick != -1 && myAxisRepeatTime < myTime)
+  {
+    // The longer an axis event is enabled, the faster it should change
+    // We do this by decreasing the amount of time between consecutive axis events
+    // After a certain threshold, send 10 events at a time (this is necessary
+    // since at some point, we'd like to process more eventss than the
+    // current framerate allows)
+    myCurrentAxisDown.count++;
+    int interval = myCurrentAxisDown.count / 40 + 1;
+    myAxisRepeatTime = myTime + kAxisRepeatSustainDelay / interval;
+    if(interval > 3)
+    {
+      for(int i = 0; i < 10; ++i)
+        activeDialog->handleJoyAxis(myCurrentAxisDown.stick, myCurrentAxisDown.axis,
+                                    myCurrentAxisDown.value);
+      myAxisRepeatTime = myTime + kAxisRepeatSustainDelay / 3;
+    }
+    else
+    {
+      activeDialog->handleJoyAxis(myCurrentAxisDown.stick, myCurrentAxisDown.axis,
+                                  myCurrentAxisDown.value);
+      myAxisRepeatTime = myTime + kAxisRepeatSustainDelay / interval;
+    }
+  }
+
   // Update joy to mouse events
   handleJoyMouse(time);
 }
@@ -270,17 +295,33 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
   // Send the event to the dialog box on the top of the stack
   Dialog* activeDialog = myDialogStack.top();
 
+  if(value > JOY_DEADZONE)
+    value -= JOY_DEADZONE;
+  else if(value < -JOY_DEADZONE )
+    value += JOY_DEADZONE;
+  else
+    value = 0;
+
   if(activeDialog->wantsEvents())
+  {
+    // Only stop firing events if it's the current key
+    if(myCurrentAxisDown.stick == stick && value == 0)
+    {
+      myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
+      myCurrentAxisDown.count = 0;
+    }
+    else
+    {
+      // Now account for repeated axis events (press and hold)
+      myCurrentAxisDown.stick = stick;
+      myCurrentAxisDown.axis  = axis;
+      myCurrentAxisDown.value = value;
+      myAxisRepeatTime = myTime + kAxisRepeatInitialDelay;
+    }
     activeDialog->handleJoyAxis(stick, axis, value);
+  }
   else
   {
-    if(value > JOY_DEADZONE)
-      value -= JOY_DEADZONE;
-    else if(value < -JOY_DEADZONE )
-      value += JOY_DEADZONE;
-    else
-      value = 0;
-
     if(axis % 2 == 0)  // x-direction
     {
       if(value != 0)
@@ -309,6 +350,8 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
         ourJoyMouse.y_down_count = 0;
       }
     }
+    myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
+    myCurrentAxisDown.count = 0;
   }
 }
 
@@ -413,6 +456,9 @@ void DialogContainer::reset()
   myLastClick.time = 0;
   myLastClick.count = 0;
 
+  myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
+  myCurrentAxisDown.count = 0;
+
   int oldX = ourJoyMouse.x, oldY = ourJoyMouse.y;
   if(ourJoyMouse.x > ourJoyMouse.x_max)
     ourJoyMouse.x = ourJoyMouse.x_max;
diff --git a/stella/src/gui/DialogContainer.hxx b/stella/src/gui/DialogContainer.hxx
index d6bd7a90b..ebc3c8756 100644
--- a/stella/src/gui/DialogContainer.hxx
+++ b/stella/src/gui/DialogContainer.hxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: DialogContainer.hxx,v 1.12 2005-12-24 22:50:53 stephena Exp $
+// $Id: DialogContainer.hxx,v 1.13 2006-01-04 01:24:17 stephena Exp $
 //============================================================================
 
 #ifndef DIALOG_CONTAINER_HXX
@@ -37,7 +37,7 @@ typedef FixedStack<Dialog *> DialogStack;
   a stack, and handles their events.
 
   @author  Stephen Anthony
-  @version $Id: DialogContainer.hxx,v 1.12 2005-12-24 22:50:53 stephena Exp $
+  @version $Id: DialogContainer.hxx,v 1.13 2006-01-04 01:24:17 stephena Exp $
 */
 class DialogContainer
 {
@@ -154,11 +154,13 @@ class DialogContainer
     DialogStack myDialogStack;
 
     enum {
-      kDoubleClickDelay = 500,
-      kKeyRepeatInitialDelay = 400,
-      kKeyRepeatSustainDelay = 50,
+      kDoubleClickDelay        = 500,
+      kKeyRepeatInitialDelay   = 400,
+      kKeyRepeatSustainDelay   = 50,
       kClickRepeatInitialDelay = kKeyRepeatInitialDelay,
-      kClickRepeatSustainDelay = kKeyRepeatSustainDelay
+      kClickRepeatSustainDelay = kKeyRepeatSustainDelay,
+      kAxisRepeatInitialDelay  = kKeyRepeatInitialDelay,
+      kAxisRepeatSustainDelay  = kKeyRepeatSustainDelay
     };
 
     // Indicates the most current time (in milliseconds) as set by updateTime()
@@ -183,6 +185,15 @@ class DialogContainer
     } myCurrentMouseDown;
     uInt32 myClickRepeatTime;
 	
+    // For continuous events (joyaxisDown)
+    struct {
+      int stick;
+      int axis;
+      int value;
+      int count;
+    } myCurrentAxisDown;
+    uInt32 myAxisRepeatTime;
+
     // Position and time of last mouse click (used to detect double clicks)
     struct {
       int x, y;     // Position of mouse when the click occured
diff --git a/stella/src/gui/GuiObject.hxx b/stella/src/gui/GuiObject.hxx
index eccd20985..6076e6477 100644
--- a/stella/src/gui/GuiObject.hxx
+++ b/stella/src/gui/GuiObject.hxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: GuiObject.hxx,v 1.16 2005-12-09 01:16:13 stephena Exp $
+// $Id: GuiObject.hxx,v 1.17 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -32,11 +32,22 @@ class Widget;
 
 typedef Common::Array<Widget*> WidgetArray;
 
+enum {
+  kCursorUp    = 256+17,
+  kCursorDown  = 256+18,
+  kCursorRight = 256+19,
+  kCursorLeft  = 256+20,
+  kCursorHome  = 256+22,
+  kCursorEnd   = 256+23,
+  kCursorPgUp  = 256+24,
+  kCursorPgDn  = 256+25
+};
+
 /**
   This is the base class for all GUI objects/widgets.
   
   @author  Stephen Anthony
-  @version $Id: GuiObject.hxx,v 1.16 2005-12-09 01:16:13 stephena Exp $
+  @version $Id: GuiObject.hxx,v 1.17 2006-01-04 01:24:17 stephena Exp $
 */
 class GuiObject : public CommandReceiver
 {
diff --git a/stella/src/gui/LauncherDialog.cxx b/stella/src/gui/LauncherDialog.cxx
index 811e656e3..97578ef45 100644
--- a/stella/src/gui/LauncherDialog.cxx
+++ b/stella/src/gui/LauncherDialog.cxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: LauncherDialog.cxx,v 1.34 2005-12-18 18:37:03 stephena Exp $
+// $Id: LauncherDialog.cxx,v 1.35 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -53,10 +53,12 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
     myQuitButton(NULL),
     myList(NULL),
     myGameList(NULL),
-    myProgressBar(NULL)
+    myProgressBar(NULL),
+    mySelectedItem(0)
 {
   const GUI::Font& font = instance()->font();
   const int fontHeight = font.getFontHeight();
+  WidgetArray wid;
 
   // Show game name
   new StaticTextWidget(this, 10, 8, 200, fontHeight,
@@ -74,31 +76,49 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
 
 #ifndef MAC_OSX
   myStartButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Play", kStartCmd, 'S');
+  myStartButton->setEditable(true);
+  wid.push_back(myStartButton);
     xpos += space + width;
   myOptionsButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Options", kOptionsCmd, 'O');
+  myOptionsButton->setEditable(true);
+  wid.push_back(myOptionsButton);
     xpos += space + width;
   myReloadButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Reload", kReloadCmd, 'R');
+  myReloadButton->setEditable(true);
+  wid.push_back(myReloadButton);
     xpos += space + width;
   myQuitButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Quit", kQuitCmd, 'Q');
+  myQuitButton->setEditable(true);
+  wid.push_back(myQuitButton);
     xpos += space + width;
 #else
   myQuitButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Quit", kQuitCmd, 'Q');
+  myQuitButton->setEditable(true);
+  wid.push_back(myQuitButton);
     xpos += space + width;
   myOptionsButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Options", kOptionsCmd, 'O');
+  myOptionsButton->setEditable(true);
+  wid.push_back(myOptionsButton);
     xpos += space + width;
   myReloadButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Reload", kReloadCmd, 'R');
+  myReloadButton->setEditable(true);
+  wid.push_back(myReloadButton);
     xpos += space + width;
   myStartButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Start", kStartCmd, 'Q');
+  myStartButton->setEditable(true);
+  wid.push_back(myStartButton);
     xpos += space + width;
 #endif
 
   // Add list with game titles
+  // The list isn't added to focus objects, but is instead made 'sticky'
+  // This means it will act as if it were focused (wrt how it's drawn), but
+  // won't actually be able to lose focus
   myList = new StringListWidget(this, instance()->font(),
                                 10, 24, _w - 20, _h - 24 - 26 - 10 - 10);
   myList->setNumberingMode(kListNumberingOff);
   myList->setEditable(false);
-  myList->setFlags(WIDGET_NODRAW_FOCUS);
-  addFocusWidget(myList);
+  myList->setFlags(WIDGET_STICKY_FOCUS);
 
   // Add note textwidget to show any notes for the currently selected ROM
   new StaticTextWidget(this, 20, _h - 43, 30, fontHeight, "Note:", kTextAlignLeft);
@@ -113,6 +133,8 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
   // Create a game list, which contains all the information about a ROM that
   // the launcher needs
   myGameList = new GameList();
+
+  addToFocusList(wid);
 }
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -336,6 +358,62 @@ string LauncherDialog::MD5FromFile(const string& path)
   return md5;
 }
 
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void LauncherDialog::handleKeyDown(int ascii, int keycode, int modifiers)
+{
+  // Only detect the cursor keys, otherwise pass to base class
+  switch(ascii)
+  {
+    case kCursorLeft:
+      mySelectedItem--;
+      if(mySelectedItem < 0) mySelectedItem = 3;
+      Dialog::setFocus(getFocusList()[mySelectedItem]);
+      break;
+
+    case kCursorRight:
+      mySelectedItem++;
+      if(mySelectedItem > 3) mySelectedItem = 0;
+      Dialog::setFocus(getFocusList()[mySelectedItem]);
+      break;
+
+    case ' ':  // Used to activate currently focused button
+      Dialog::handleKeyDown(ascii, keycode, modifiers);
+      break;
+
+    default:
+      if(!myList->handleKeyDown(ascii, keycode, modifiers))
+        Dialog::handleKeyDown(ascii, keycode, modifiers);
+      break;
+  }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void LauncherDialog::handleJoyAxis(int stick, int axis, int value)
+{
+  // We make the (hopefully) valid assumption that all joysticks
+  // treat axis the same way.  Eventually, we may need to remap
+  // these actions of this assumption is invalid.
+  // TODO - make this work better with analog axes ...
+  int key = -1;
+  if(axis % 2 == 0)  // x-direction
+  {
+    if(value < 0)
+      key = kCursorLeft;
+    else if(value > 0)
+      key = kCursorRight;
+  }
+  else   // y-direction
+  {
+    if(value < 0)
+      key = kCursorUp;
+    else if(value > 0)
+      key = kCursorDown;
+  }
+
+  if(key != -1)
+    handleKeyDown(key, 0, 0);
+}
+
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
                                    int data, int id)
diff --git a/stella/src/gui/LauncherDialog.hxx b/stella/src/gui/LauncherDialog.hxx
index 685d59809..ec42deb5e 100644
--- a/stella/src/gui/LauncherDialog.hxx
+++ b/stella/src/gui/LauncherDialog.hxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: LauncherDialog.hxx,v 1.13 2005-08-22 18:17:10 stephena Exp $
+// $Id: LauncherDialog.hxx,v 1.14 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -36,10 +36,6 @@ class OSystem;
 #include "bspf.hxx"
 
 enum {
-  kStartCmd   = 'STRT',
-  kOptionsCmd = 'OPTI',
-  kReloadCmd  = 'RELO',
-  kQuitCmd    = 'QUIT',
   kChooseRomDirCmd  = 'roms',  // rom select
   kChooseSnapDirCmd = 'snps',  // snap select
   kRomDirChosenCmd  = 'romc',  // rom chosen
@@ -53,12 +49,16 @@ class LauncherDialog : public Dialog
                    int x, int y, int w, int h);
     ~LauncherDialog();
 
+  protected:
+    virtual void handleKeyDown(int ascii, int keycode, int modifiers);
+    virtual void handleJoyAxis(int stick, int axis, int value);
     virtual void handleCommand(CommandSender* sender, int cmd, int data, int id);
 
-  protected:
     void updateListing(bool fullReload = false);
     void loadConfig();
 
+    virtual bool wantsEvents() { return true; }
+
   protected:
     ButtonWidget* myStartButton;
     ButtonWidget* myOptionsButton;
@@ -79,6 +79,16 @@ class LauncherDialog : public Dialog
     void loadListFromCache();
     void createListCache();
     string MD5FromFile(const string& path);
+
+  private:
+    int mySelectedItem;
+
+    enum {
+      kStartCmd   = 'STRT',
+      kOptionsCmd = 'OPTI',
+      kReloadCmd  = 'RELO',
+      kQuitCmd    = 'QUIT'
+    };
 };
 
 #endif
diff --git a/stella/src/gui/ListWidget.cxx b/stella/src/gui/ListWidget.cxx
index 26186b323..f860b677b 100644
--- a/stella/src/gui/ListWidget.cxx
+++ b/stella/src/gui/ListWidget.cxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: ListWidget.cxx,v 1.37 2005-12-21 19:31:18 stephena Exp $
+// $Id: ListWidget.cxx,v 1.38 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -287,33 +287,33 @@ bool ListWidget::handleKeyDown(int ascii, int keycode, int modifiers)
         }
         break;
 
-      case 256+17:  // up arrow
+      case kCursorUp:
         if (_selectedItem > 0)
           _selectedItem--;
         break;
 
-      case 256+18:  // down arrow
+      case kCursorDown:
         if (_selectedItem < (int)_list.size() - 1)
           _selectedItem++;
         break;
 
-      case 256+24:  // pageup
+      case kCursorPgUp:
         _selectedItem -= _rows - 1;
         if (_selectedItem < 0)
           _selectedItem = 0;
         break;
 
-      case 256+25:	// pagedown
+      case kCursorPgDn:
         _selectedItem += _rows - 1;
         if (_selectedItem >= (int)_list.size() )
           _selectedItem = _list.size() - 1;
         break;
 
-      case 256+22:  // home
+      case kCursorHome:
         _selectedItem = 0;
         break;
 
-      case 256+23:  // end
+      case kCursorEnd:
         _selectedItem = _list.size() - 1;
         break;
 
diff --git a/stella/src/gui/ListWidget.hxx b/stella/src/gui/ListWidget.hxx
index 87dccd5aa..14384b625 100644
--- a/stella/src/gui/ListWidget.hxx
+++ b/stella/src/gui/ListWidget.hxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: ListWidget.hxx,v 1.14 2005-09-30 18:17:29 stephena Exp $
+// $Id: ListWidget.hxx,v 1.15 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -70,7 +70,7 @@ class ListWidget : public EditableWidget
     virtual void handleCommand(CommandSender* sender, int cmd, int data, int id);
 
     virtual GUI::Rect getRect() const;
-    virtual bool wantsFocus() { return true; }
+    virtual bool wantsFocus() { return !isSticky(); }
 
     void startEditMode();
     void endEditMode();
diff --git a/stella/src/gui/StringListWidget.cxx b/stella/src/gui/StringListWidget.cxx
index 6a7cb9465..8c3fd1abf 100644
--- a/stella/src/gui/StringListWidget.cxx
+++ b/stella/src/gui/StringListWidget.cxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: StringListWidget.cxx,v 1.2 2005-08-23 18:32:51 stephena Exp $
+// $Id: StringListWidget.cxx,v 1.3 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -67,7 +67,7 @@ void StringListWidget::drawWidget(bool hilite)
     // Draw the selected item inverted, on a highlighted background.
     if (_selectedItem == pos)
     {
-      if (_hasFocus && !_editMode)
+      if ((_hasFocus && !_editMode) || isSticky())
         fb.fillRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, kTextColorHi);
       else
         fb.frameRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, kTextColorHi);
diff --git a/stella/src/gui/Widget.hxx b/stella/src/gui/Widget.hxx
index 4e95cfcfb..7b387b2c7 100644
--- a/stella/src/gui/Widget.hxx
+++ b/stella/src/gui/Widget.hxx
@@ -13,7 +13,7 @@
 // See the file "license" for information on usage and redistribution of
 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
 //
-// $Id: Widget.hxx,v 1.43 2005-12-24 22:09:36 stephena Exp $
+// $Id: Widget.hxx,v 1.44 2006-01-04 01:24:17 stephena Exp $
 //
 //   Based on code from ScummVM - Scumm Interpreter
 //   Copyright (C) 2002-2004 The ScummVM project
@@ -44,8 +44,9 @@ enum {
   WIDGET_TRACK_MOUSE  = 1 << 6,
   WIDGET_RETAIN_FOCUS = 1 << 7,
   WIDGET_NODRAW_FOCUS = 1 << 8,
-  WIDGET_WANTS_TAB    = 1 << 9,
-  WIDGET_WANTS_EVENTS = 1 << 10
+  WIDGET_STICKY_FOCUS = 1 << 9,
+  WIDGET_WANTS_TAB    = 1 << 10,
+  WIDGET_WANTS_EVENTS = 1 << 11
 };
 
 enum {
@@ -73,7 +74,7 @@ enum {
   This is the base class for all widgets.
   
   @author  Stephen Anthony
-  @version $Id: Widget.hxx,v 1.43 2005-12-24 22:09:36 stephena Exp $
+  @version $Id: Widget.hxx,v 1.44 2006-01-04 01:24:17 stephena Exp $
 */
 class Widget : public GuiObject
 {
@@ -115,6 +116,7 @@ class Widget : public GuiObject
 
     bool isEnabled() const      { return _flags & WIDGET_ENABLED;      }
     bool isVisible() const      { return !(_flags & WIDGET_INVISIBLE); }
+    bool isSticky() const       { return _flags & WIDGET_STICKY_FOCUS; }
     bool wantsEvents() const    { return _flags & WIDGET_WANTS_EVENTS; }
 
     void setID(int id)  { _id = id;   }