       "FACE_3": 'action1'
       "START_FORWARD": 'start'
 
-    @adminControllerMailbox = @postOffice.newMailbox()
-    KeyboardController3.bindKeys @adminControllerMailbox.address,
+    # @adminControllerMailbox = @postOffice.newMailbox()
+    # KeyboardController3.bindKeys @adminControllerMailbox.address,
+    @adminController = createKeyboardSignal @postOffice,
       "g": 'toggle_gamepad'
       "b": 'toggle_bgm'
       "p": 'toggle_pause'

          input = input.setIn(['controllers' ,e.get('tag'), e.get('control')], isDown)
    input

class MetroidSignalsDelegate
  constructor: ({componentInspector,@devUI,@systemLogInspector}) ->

    @postOffice = new PostOffice()

    @playerControllerMailbox = @postOffice.newMailbox()
    KeyboardController3.bindKeys @playerControllerMailbox.address,
      "right": 'right'
      "left": 'left'
      "up": 'up'

    dtEvents = @dtMailbox.signal
      .map((dt) -> Map(type:'Tick',dt:dt))

    playerControlEvents = @player1KbController.merge(@player1GpController)
      .dropRepeats(Immutable.is)
      .map((event) -> event.set('tag','player1'))

    adminControlEvents = @adminController
      .dropRepeats(Immutable.is)
      .map((event) -> event.set('tag','admin'))


    # For each time slice, smush all events into a composite 'input' structure
    input = dtEvents
      .merge(playerControlEvents)
      .merge(adminControlEvents) # all dt, keybd and gp events into one stream
      .sliceOn(dtEvents)         # batch up the events in an array and release on arrival of dt event
      .map(inputBundler(@defaultInput)) # compile the 'input' structure (controller states, dt and static game data)


    adminState = input
      .foldp(Admin.update, Admin.initialState()) # process administrative controls and state first


    #
    # Rollingistory: a value object containing a rolling list of game state values...
    # AND a pointer to where we are in that history.  (Often, current() is the most recently
    # calculated game state, but our admin state may decide to adjust it back or forward 
    # through the history buffer.)
    # 
    # As we calculate new game states, we accumulate a history of game states.
    #
    # This stage of the pipeline must produce an updated snapshot of the game universe
    # and our place in that universe.
    #
    # NOTE: 'game state' is a nebulous term.  TheGame's idea of state looks like {mode:'adventure', gameState:(entityStoreGuts)}.
    # Some code refers to 'game state' in this sense, other code (like the view machine) considers the 'entity store guts' to be game state.
    #

    # (convenience: simplify invocation of game engine updates)
    updateGame = (input,s) ->
      [s1,_] = TheGame.update(s,input)
      return s1

    initialHistory = RollingHistory.add(RollingHistory.empty, TheGame.initialState())

    # Given a new admin state, change history....
    updateHistory = (admin, history) ->
      input = admin.get('input')
      game = RollingHistory.current(history)
      if admin.get('paused')
        # (when paused, admin controls may choose to alter history in specific ways)
        if admin.get('replay_back')
          history = RollingHistory.back(history)     #  ...by stepping back in time (min=oldest retained gamestate)
        else if admin.get('replay_forward')
          history = RollingHistory.forward(history)  #  ...by stepping forward in time (max=newest gamestate)
        else if admin.get('step_forward')
          input1 = input.set('dt', admin.get('stepDt'))
          # (if we're currently in the past, step_forward starts a new timeline... wipe the previous future)
          history = RollingHistory.truncate(history)
          history = RollingHistory.add(history, updateGame(input1, game)) # ...by calc'ing a new gamestate due to single-frame step
      else
        # (the normal game-play scenario)
        if admin.get('truncate_history')
          # (if we're currently in the past, step_forward starts a new timeline... wipe the previous future)
          history = RollingHistory.truncate(history)
        history = RollingHistory.add(history, updateGame(input,game)) # ...by calc'ing the next "natural" gamestate based on dt and controller inputs

      return history

    # State of history over time:
    history = adminState
      .foldp(updateHistory, initialHistory)
      .dropRepeats(Immutable.is)

    # When gameState changes, update view:
    history.subscribe (h) =>
      @viewMachine.update2(RollingHistory.current(h).get('gameState'))

  update: (dt) ->
    @dtMailbox.address.send dt
