Steam Controller

Steam Controller

Not enough ratings
Editing .vdf steam controller files
By Volatile
An attempt at figuring out, and documenting, how to edit the .vdf config files directly for the steam controller.
THIS GUIDE IS BY NO MEANS COMPLETE. I'll probably add more over the next weeks/months.
This is a documentation of my trial and error adventures into the undocumented land of .vdf file writing and editing.

My hope is that this can help someone else overcome the jungle of randomness that is the .vdf file without having quite as many loading errors as I had.

What I will be documenting is the "controller_mappings version 3" section of the .vdf file.

  • Do not attempt to use this guide unless you know what you're doing.
  • The chances of you ♥♥♥♥♥♥♥ up your config is great, SO MAKE BACKUPS FREQUENTLY.
  • Unless you can see the terminal output from Steam, the only "error message" you will get is that you can't find your config in the list of configs to load for your controller. Welcome to the dark and harsh place that is .vdf editing.

It is assumed that you know how to edit pure text files, and that you know how to look for files in the steam directory of whatever operating system you're using.
Saving and loading the config file
The easiest way to
  • find out where the config files are stored for your game
  • find out which config file you actually want to poke arond in
  • fint out what structure a steam controller config file has at the moment
is to save a config file LOCALLY from big picture mode, then go to
the userdata folder in your steam directory and do a seach for your .vdf file; If you save the config as "foo_bar" in BPM, the vdf file will have the name foo_bar_0.vdf, with all characters lower case

If you don't save the file as a local config, you will instead have two foo_bar_0.vdf in different locations in userdata, and presumably some files on a server somewhere as well. If you do this, you're on your own - I haven't yet figured out if there's a way to edit those files in any meaningful way.

(I'm not sure yet if this step is neccessary for games in general since I'm focusing on editing my desktop config atm.)
To reload the desktop mode config files, I first exit the desktop mode config, enter the big picture mode config, exit big picture mode config and go back to desktop mode config. If steam deems the config file to be valid, it will show up in the list of configs - if not, you have to change back whatever it was you did to make the file invalid. (Remember what I said about backups?)

I assume the same is true about ordinary games:
To make Steam load in your changed config file, you must first force steam to load the config files for some other game, by going in to that game in BPM and clicking on controller configuration, then go back again to the game whose files you were configuring.

Sometimes steam gets the idea that the last local save was an autosave, and then promptly fails to access any and all local saves (you'll see them in the menu, but steam fails when it tries to bring you into the config interface for the save). I've only been able to solve this by restarting steam - but on the plus side, at least it is solvable by restarting steam!
A vdf file consists of strings, braces, whitespace and comments.
Everything on a line after // is ignored
/* */ is not a comment, and will make steam cry. Don't try it.

The file is organized into multiple instances and hiearchies of
  • a line with a pair of string
  • a string paired with a group of pairs grouped by {}
Here are some words I'll use in this guide.

A tag is the string that defines a value or section.
"foo" {}
"foo" "value"

A value is a string associated with a tag
"foo" "value"

A section is a { ,followed by some code, wollowed by a }
"foo" { other stuff }

If a tag "foo" has a section as a value, I'll call the tag and value together a foo section
"foo" {}

If a tag "foo" has a simple string as a value, I'll call it a foo value or simply the "foo".
"foo" "value"

If a foo section itself contains a section, I'll call the latter section a "foo subsection".

} // ("bar" is a "foo subsection")

If the tag names themselves of some section aren't fixed but rather the same as a value of some tag of some other sections, I'll call them "value tags".
"etaoin" "value"
"shdlu" "value"
If they define sections, I'll call them "value sections".
  • "etaoin"
    • "foo" "1"

    • "foo" "2"
General file structure
Value pairs, braces and strings, oh my!
The general structure of the file consists of pairs of tags and values; with the value on the same line as the tag when the value is a simple string, and with the value starting on the next line if the value is a section enclosed in { } 's
Each section in turn consists of a number of other tags and values, some of which are subsections containing their own values and subsections.

Numbers and strings
While all values are either strings or sections, of the strings are treated as numbers! In particular, all "id" tags seems to get converted to "numbers" in a javascript-esque way, namely:
  • Take any leading numbers in the string, and let that be the numerical value.
  • If there are no leading numbers in the string, the numerical value of the string is 0.

So the strings "22", "22 foo" and "22bar" all will be interpreted as 22, whereas "0", "foo" and "bar" all will be interpreted as 0.
This is particularly important for id tags: You can add text after the numerical part of the string value to clarify what the section does, but if you omit the initial numerical part, the id value will clash with the section with id "0", and whichever comes later in the file will overwrite the other when the file is loaded.

For instance, if we have
  • {
    • "id" "0"
  • {
    • "id" "foo"
  • {
    • "id" "bar"
then only group "bar" will be used when loading the file.
Steam will report no errors for this.

Booleans, options that are either on or off/true or false, have either the value "1" or the value "0", respectively.
The "controller_mappings" section
This section is the top section for a controller config file, enclosing all others sections and values.
  • version [num]
    I'm writing this guide for version "3" of the file. I can give no guarantees that anything I say here will be valid at all for other versions.
  • title [string]
    The title of the config shown in BPM
  • description [string]
    The description of the config in BPM
  • creator [num]
    Your steam ID, presumably.
  • controller_type [string]
    It's probably a bad idea to poke around with this one. Mine says "controller_steamcontroller_gordon"
  • actions (one)
    This section list the names of all action sets for the controller
  • group (many)
    These sections list one button specification each.
  • preset (many)
    Each preset links a number of "group" sections to one "action", specifying an action set per preset section
  • settings (one)
    If you want automagic switching between action sets based on whether the mouse is visible, this is where to do it.
The "group" sections
Specifies a configuration for a "button group", viz the joystick, one of the trackpads, the four diamond buttons, one of the trigger buttons, or all the rest of the buttons.
IMPORTANT Each button group can only be used for one group type! If you try to assign a button group to, for example, both the left trackpad and the joystick, steam will not load in your config.
Which button group a certain group describes is defined outside of the button group itself, in the "preset" sections.
While a group section can only belong to one button group, several preset sections can refer to the same group section as long as it is for the same button group.

  • id [num]
    The unique id number of the group. If two groups have the same number, one of them will silently be ignored by steam.
    The group id is used in the action sections to build up a full action set for the config.

  • mode [string]
    The "mode" of the group. It can have the following values:
    • dpad
      Defines a dpad layout for an applicable button group.
    • four_buttons
      Defines a four buttons layout for an applicable button group.
    • absolute_mouse
    • switches
      Defines the six buttons not covered by the other button groups.
    • trigger
      Defines one of the trigger buttons.
    • scrollwheel
      Defines scrollwheel behaviour for an applicable button group.
    • ...

  • inputs
    Lists the input definition subsections for the button group.
    Each subsection listed below can contain the subsection hiearchy
    • "activators" {
      • "Full_Press" {
        • "bindings" {
        • "settings" {
    Valid input subsections for different modes:
    • dpad subsections:
      • dpad_north
      • dpad_south
      • dpad_west
      • dpad_east

    • four_buttons subsections:
      • button_A
      • button_B
      • button_X
      • button_Y

    • absolute_mouse subsections:
      • click

    • switches subsections:
      • button_escape
      • button_menu
      • left_bumper
      • right_bumper
      • button_back_left
      • button_back_right

    • trigger subsections:
      • edge
      • click

    • scrollwheel subsections:
      • scroll_clockwise
      • scroll_counterclockwise
      • click

    • ...

    The subsections under FullPress:
    • bindings
      Contains multple "binding" values, each specifying a button/mouse click or some other form of action.

      The values are one big string per value, for instance "mouse_button LEFT" or "controller_action CHANGE_PRESET 32765 0 1"

      Verified valid binding values:
      • mouse_button
      • mouse_wheel
      • key_press
        • A|B|C|...|Z
      • controller_action
        • CHANGE_PRESET 32765 0 1
          Change to previous action set
        • CHANGE_PRESET 32766 0 1
          Change to next action set

    • settings
      Valid settings include:
      • haptic_intensity [num]
      • interruptable [bool]
The "actions" section
Defines the names of the action sets.
The tag of each section in here defines the internal name of an action set. The section tags can NOT contain spaces, or the file won't load.

When steam saves the config file, the first section will have the tag "Default", while the rest will have tags like "Preset_1000001", "Preset_1000002" etc. These tags can be changed as long as you also change them in their corresponding preset section. (See 'The "preset section'.)

Each value section contains the following values:
  • title [string]
    The name of the action set as shown in BGM.
    Can contain spaces.
  • legacy_set [num? bool?]
    Set to "1" for me. Let's keep it that way.
The "preset" sections
Defines which button group definitions go into which action set.
  • id [num]
    The distinct id of the action set. "0" is the lowest id. The higher the id, the later in the list of action sets the action set will be.
    TIP If you want to swap two action sets in your config, just swap the id's of their preset sections!

  • name [name of an actions subsection]
    The internal name, specified by a section name under the "actions" main section, that this preset section is to define.

  • group_source_bindings
    This section contsists of value tags.
    Each tag in this section is the id of a group section.
    Each value is a combination of a button group and an activation state, e.g. "switch active"
    Possible button groups:
    • switch
    • button_diamond
    • joystick
    • left_trackpad
    • right_trackpad
    • left_trigger
    • right_trigger
    Possible activation states:
    • active
      the normal config for the button group
    • active modeshift
      the modeshift config for the button group
    • inactive
      the button group is not used
The "settings" section
Some global settings for the config.
  • action_set_trigger_cursor_show [bool? action set id? num?]
  • action_set_trigger_cursor_hide [bool? action set id? num?]
Errors/Error Messages
If you have access to the Steam cilent terminal output, you'll sometimes get error messages when steam fails to load in your file. Here I'll list the ones I've gotten so far, with an explanation of what they mean.
  • ...

Sometimes steam gets the idea that the last local save was an autosave, and then promptly fails to access any and all local saves (you'll see them in the menu, but steam fails when it tries to bring you into the config interface for the save). I've only been able to solve this by restarting steam - but on the plus side, at least it is solvable by restarting steam!
< >
Tony Gwhak Feb 20 @ 6:02am 
my defult steam controller keyboard GUI has changed would you beable to help change it back here are all the details. its changed to a ps4 looking gui but its buggy and freezes or wont show when typing on desktop controllers config. might be a messed up vdf file? it happend after i added a nonsteam game to steam and in game the desktop config was loded not teh ingame config i kept spaming the joystick to open the keyboard gui and tehn thi new one showed up, cant revert back even after restarting pc and steam also uninstalling the nonsteamgame, nothing works, now its a paint to try and attempt to type. if this gui wansnt bugg it would be way better then the original steam keyboard gui. anyway read this post ive gon in to further details with screenshots of waht the GUI has been chnaged to. thanks
brecht2202 Jul 19, 2022 @ 11:21am 
Hey do you know how I can use the '<' key as some kind of key-press binding?
Jamessuperfun Jun 24, 2022 @ 8:34am 
This seems like a great guide! I've been trying to see if I can get the Steam Deck 'Neptune' controller to provide trackpad input on Windows in the Deck UI. It'll eventually replace Big Picture (you can launch it by running Steam with -steamos3 -steampal -steamdeck -gamepadui), but the main problem is input. It disables the trackpads while the active window, but gets stuck in this profile after a game is opened and closed. There's no option to customise this default profile either.

I've been trying to find the default binding file and edit it, but I'm not sure where I need to modify. Any ideas?
keyborges Feb 5, 2021 @ 3:53pm 
Anyways, if you happen to go back to this kind of stuff again consider taking a look in the threads about the lost Daisy Wheel Steam BP keyboard. I found this and I wonder if you'd be as amazed as me with the lost feature, and maybe you're qualified enough to make use of it in Steam, because sadly I am not. It would create value to your .vdf reverse engineering knowledge, and maybe you could sell it to Steam or put it in your git to make a case of your effort. Idk, I'm just a talkative random lol! Godspeed, my friend, whatever you're doing out there in the world.
keyborges Feb 5, 2021 @ 3:53pm 
You are a magnificently cool person. I commented here not expecting much, didn't even know if your profile was active or not, but I wanted to keep record of things if I ever happen to edit those again. I imagine you spent a lot of time reverse engineering this stuff, while I wasted part of my time just trying to clean the file and put the "group id"s in a friendly order. At the end of the day, what I did doesn't worth the effort, as the Steam editor will mess it up again and also not every controller will work with the multiples of 8 I used. What you did, tho, was the glorious bridge between me giving up on my attempt and actually making my controller config usable.
Volatile  [author] Nov 29, 2020 @ 9:46am 
Cool! Thanks for the addendum, keyborges, glad you liked my guide - and nice config you've made! :)
If I ever get steam to work in Linux again (or somehow manage to get debug/terminal output from steam in windows) I'll probably continue to develop this guide further.

I've actually never heard of volatile the game! Once in the dawn of time I chose this username cause I liked the volatile pragma used in the programming language C.
keyborges Nov 3, 2020 @ 3:27pm 
Desktop: steam://controllerconfig/413080/2276658879
keyborges Nov 3, 2020 @ 1:15pm 
UPDATED LINK TO MY TEMPLATE: steam://controllerconfig/413090/2276566314

In "title" it's possible to call context layers e.g.: "title" "#Chat" in Big Pitcture, instead of just "Chat", (just "Chat" will only work with original set name "preset_1000004" for some reason). Last but not least, when creating a layer, if you wish to overlap the parent layer for joysticks, trackpads, etc... I think it's good practice to dispose gameactions as follows:
"child_name" "parent_name action"
"parent_name" "action"
inside the "child" group, will work only if the layer isn't related to a different "virtual mode" than the "parent". I'm still not sure what is a "virtual mode", but I'm guessing it's the same as what I called "context layer" but for layers and sets.

Thank you so much, Volatile, one more time. I wonder if you're related to the developing team of Volatile the game.
keyborges Nov 1, 2020 @ 10:14pm 
Thanks! It was the only helpful thing I could find online. I know little about Steam, but thanks to you I made this ( steam://controllerconfig/413090/2275003946 ) template for the big picture mode (kind of useless, I know, but complex enough and general enough). I'd like to add to your post that there are inconsistencies in the vdf/app, as in the 'modeshift' the "joystick" as an activator represents the right joystick, but if you manually edit to "left_..." it's possible to switch it to the left joystick; Or as said by the user lagamemnon in another post, the vdf numerical values are not directly related to the slider notches. As said by you, .vdf editing is a dark and harsh place.