Reference
Controller config JSON
The format of global and per-game controller profiles, the actions and button names, and how files are validated.
On this page
| File | Scope |
|---|---|
config/controller/global.json | The loader and every game without its own profile |
config/controller/games/<id>.json | One game |
Both are written by Controller settings. You can also write them by hand.
The default profile
{
"format": "renpy-switch-loader/controller",
"version": 1,
"bindings": {
"confirm": ["A"],
"back": ["B"],
"hide_ui": ["X"],
"history": ["Y"],
"rollback": ["L"],
"rollforward": ["R"],
"auto": ["ZL"],
"skip": ["ZR"],
"game_menu": ["Plus"],
"quick_menu": ["Minus"],
"up": ["DUp", "NavUp"],
"down": ["DDown", "NavDown"],
"left": ["DLeft", "NavLeft"],
"right": ["DRight", "NavRight"],
"click": ["RStick"],
"overlay": ["LStick"]
},
"deadzone": 0.15,
"cursor_speed": 0.6,
"cursor_accel": 1.5,
"repeat_delay_ms": 400,
"repeat_interval_ms": 90,
"nav_stick": "left",
"cursor_stick": "right",
"cursor_visible": true
}Actions
The 16 logical actions. Each takes a list of buttons.
| Action | Does | Essential |
|---|---|---|
confirm | Confirm, advance | yes |
back | Back, cancel; rollback in a game | yes |
hide_ui | Hide the text box | |
history | Dialogue history | |
rollback, rollforward | Roll back, roll forward | |
auto | Auto-forward on/off | |
skip | Skip while held | |
game_menu | Game menu | yes |
quick_menu | Quick menu | |
up, down, left, right | Navigate | yes |
click | Mouse click at the cursor | |
overlay | Loader overlay (not built yet) | yes |
Button names
Nintendo labels, never SDL gamepad names: A, B, X, Y, L, R, ZL, ZR, Plus, Minus, LStick, RStick (stick presses), DUp, DDown, DLeft, DRight, SL, SR (the rail buttons of a detached Joy-Con), and NavUp, NavDown, NavLeft, NavRight for the navigation stick’s directions.
Buttons are read straight from libnx HID, not through SDL’s GameController layer, which names buttons by position (Xbox layout) and would turn Nintendo A into “B”.
Other fields
| Field | Type | Default |
|---|---|---|
deadzone | number | 0.15 |
cursor_speed | number | 0.6 |
cursor_accel | number | 1.5 |
repeat_delay_ms | int | 400 |
repeat_interval_ms | int | 90 |
nav_stick | "left" or "right" | "left" |
cursor_stick | "left" or "right" | "right" |
cursor_visible | bool | true |
Validation
Files are loaded strictly. A file is rejected when it has:
- an unknown action or button, or a wrong type;
- a
versionnewer than the loader understands; - an essential action left unbound.
Actions missing from a file keep their default, so new actions need no migration. A rejected file falls back to <file>.bak, then to the defaults. Saving refuses conflicting or incomplete mappings.
Saves are atomic. Horizon’s rename does not replace an existing file, so a save writes x.tmp, fsyncs it, moves x to x.bak, then moves x.tmp to x.