Joymappings

From vice-emu
Revision as of 11:04, 6 March 2023 by Compyx (talk | contribs) (Add moving hotkeys code into shared)
Jump to navigation Jump to search

For a long time the SDL port has had a joystick mappings file. There are 2 sample ones: data/C64/sdl_joymap_thec64.vjm and data/C64/sdl_joymap_ps3.vjm.

These files contain associations between host joystick actions and emulator actions. Possible actions include a corresponding emulated joystick action, a shortcut to an emulator menu action etc.

The branch branches/fabrizio/3.7-joystick-mapping-2 moves the joystick mappings file to the generic joystick code, therefore making it available to the Gtk3 port as well.

The file name has the form {sdl,gtk3,headless}-joymap-{C64,C64SC,...}.vjm. Its format is documented in a comment in the sample file itself.

In order to port the feature to the generic code, the event UI_FUNCTION (shortcuts to menu actions) got lost. It was implemented in a very SDL-specific way, and a cross-platform implementation that allows shortcuts from SDL and GTK3 should be written instead.

Mapping file

A line has 4 mandatory columns:

  1. joystick number (zero-based index of the hardware joystick)
  2. input type
    1. axis
    2. button
    3. hat
  3. input index
    • for buttons, it is the zero-based index of the button
    • for axes
      • if the action is 6 (POT_AXIS), it is the zero-based index of the axis
      • otherwise, 0 and 1 are respectively the positive and negative directions of axis 0; 2 and 3 are respectively the positive and negative directions of axis 1 etc. In formulas: axis=inputindex/2 (integer division), direction = positive if inputindex % 2 ==0 , negative if inputindex % 2 ==1.
    • for hats, 0, 1, 2 and 3 are respectively up, down, left and right of hat 0; 4, 5, 6 and 7 are respectively up, down, left and right of hat 1, etc.
  4. action (enum joystick_action_t in joystick.h)
  1. NONE: none
  2. JOYSTICK: emulated joystick action
  3. KEYBOARD: emulated keyboard action
  4. MAP: SDL-only. Only works while the SDL settings menu is active. If a joystick action mapped to this is performed, the user is asked to press a key, which will become a hotkey to select the currently-selected menu
  5. UI_ACTIVATE: go to the settings menu (SDL) show the settings dialog (Gtk3)
  6. UI_FUNCTION: shortcut to a specific UI function. UNSUPPORTED AT THE MOMENT
  7. POT_AXIS: (only for axes of hardware joysticks) the analog value of the axis is the value of the emulated potentiometer

For some actions, more columns are present:

  • JOYSTICK
  1. emulated joystick pin. Same values as reading the corresponding CIA register.
    1. up
    2. down
    3. left
    4. right
    5. fire
    6. fire 2
    7. fire 3

Blacky note: In vice we also emulate snes pads, these need to be able to be controlled as well, and so the emulated joystick pin needs to be renamed (more like emulated joystick input) and extended, some of the old pins/inputs can be reused, and in such a case we get the following:

  1. joystick up / snes pad up
  2. joystick down / snes pad down
  3. joystick left / snes pad left
  4. joystick right / snes pad right
  5. joystick fire 1 / snes pad A button
  6. joystick fire 2 / snes pad B button
  7. joystick fire 3 / snes pad X button
  8. snes pad Y button
  9. snes pad left bumber
  10. snes pad right bumber
  11. snes pad select button
  12. snes pad start button

And this can be extended if other joystick devices become available with more buttons than we currently map for.

  • KEYBOARD
  1. row in the keyboard matrix layout
  2. column in the keyboard matrix layout
  • POT_AXIS
  1. which potentiometer is affected
    1. Pot-X
    2. Pot-Y

Technical

When a hardware joystick action is performed, the selected joystick driver (Gtk3) ui_dispatch_events() (SDL) call joy_axis_event() or joy_button_event() or joy_hat_event(). These functions read what that joystick action is mapped to, and perform the mapped action.

Mappings are stored in the static array joystick_devices, declared in joystick.c, that has one element per registered hardware joystick. Mappings are stored in each element's axis_mapping, button_mapping and hat_mapping, each an array with one element per axis/button/hat. The mappings are initialised from the joystick mappings file, or with default values if no joystick mappings file is present.

Example

Take this sample line from data/C64/sdl_joymap_ps3.vjm

# O -> Space
0 1 1 2 7 4

First column: HW joystick 0

Second column: input type is button (1)

Third column: input index 1, so button 1

Fourth column: action KEYBOARD (2)

Fifth and sixth columns: Space (7 and 4 in the matrix)

Does it really make sense to put the number of the hardware joystick into the mapping file? I'd expect i can use the same mapping file for more than one controller Gpz (talk) 19:09, 20 February 2023 (CET)


TODO

This section will list the various tasks that need to be undertaken to properly implement the joystick mappings in the UIs and also make it easily implementable in future UIs. I (Compyx) will be collecting the various tasks here, moving them from other pages in the Wiki so we have a central place to keep track of progress.

The following is just copy/paste from other pages in the Wiki, I'll be reorganizing them into a more workable state later:

General

  • Change the resources "JoyDevice{N}" to use strings with device identifiers instead of an index of the predefined and connected devices. So for example a Logitech F710 controller would be "001:006:046d:c21f" (usb-bus 1, device-no 6, vendor-Id 046d, product-Id c21f). We'll need archdep code to translate the strings into something the underlying arch driver can use, so at least handlers for Windows, MacOS, Linux and the various BSDs.
Relying on the device product/model ID won't be enough: a user can have multiple controllers of the same model.
  • Provide a joymap file per device identifier that can be loaded/edited/deleted, perhaps auto-load when JoyDevice{N} contains such an identifier.
  • Make the joymap files use (UI) action identifiers instead of the "menu paths" SDL does.
  • Make the joymap files human-readable by not doing what SDL does: for example: don't use 0-3 for input type, use ["axis", "button", "hat", "ball"], don't use 0-6 for the 'action' row, use "none" (or leave it out)", "joystick", "keyboard", "ui-action, "pot".
  • keep in mind there needs to be a way to map both "paddles" and "joysticks"
  • Dialogs need to written to handle all of this.

SDL UI

  • the SDL "menu actions" should use fixed numeric IDs for the mapping to keys/joystick instead of "menu pathes" which break when the menu is rearranged
  • SDL1/2 joystick mapping improvements
    • Make the 'extra joystick options' menu show what they are already mapped to
    • Add menu joystick actions mapping support to the 'extra joystick options' menu

GTK3 UI

A lot =)


Actions

This will be the list of things to do and the place to keep track of progress:

Actions to be undertaken for full configurable joystick mappings
Action Description Who Status Depends on Remarks
UUIDs Figure out how to obtain UUIDs for controllers on Linux, BSD, MacOS and Windows ? 0%
SDL UI actions Rework SDL menu system to use UI actions Compyx 0% ?
GTK joycode Make the Gtk3 UI use the new joy mapping code ? 0% ?
Joymap files Update syntax of joymap files to use a human-readable format (text instead of magic numbers). If the files are easier to read and write users can produce joymaps for controllers they own, which we can then include in VICE. This will be especially handy until we have proper UI support for creating the mappings. Compyx 0% ?
Resources Change and add resources to use UUIDs for controllers and mapping joymap files to controllers. Get rid of the 0-4 for 'none', 'numpad', 'keyset A', 'keyset B' and 4+ for whatever controller was plugged in first: change Joy%d to strings. ? 0% UUIDs
Hotkeys Move most of the hotkeys code into arch/shared so the hotkey files and the parser can be shared between UIs. The hotkeys code relies on UI actions, so if we make the hotkeys parser use a callback when it encounters a hotkey definition we can use the hotkeys code for all UIs. For example: void hotkey(int action_id, int keysym, unsigned modifiers). Compyx 0% SDL UI actions