mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2024-10-22 20:48:17 +08:00
227 lines
9.5 KiB
Python
227 lines
9.5 KiB
Python
#controller vdf script by mr_goldberg
|
|
#generates controller config from a vdf
|
|
import vdf
|
|
import sys
|
|
import os
|
|
import traceback
|
|
|
|
keymap_digital = {
|
|
"button_a": "A",
|
|
"button_b": "B",
|
|
"button_x": "X",
|
|
"button_y": "Y",
|
|
"dpad_north": "DUP",
|
|
"dpad_south": "DDOWN",
|
|
"dpad_east": "DRIGHT",
|
|
"dpad_west": "DLEFT",
|
|
"button_escape": "START",
|
|
"button_menu": "BACK",
|
|
"left_bumper": "LBUMPER",
|
|
"right_bumper": "RBUMPER",
|
|
"button_back_left": "A",
|
|
"button_back_right": "X",
|
|
"button_back_left_upper": "B",
|
|
"button_back_right_upper": "Y",
|
|
"": "",
|
|
"": "",
|
|
"": "",
|
|
"": "",
|
|
}
|
|
|
|
def add_input_bindings(group, bindings, force_binding=None, keymap=keymap_digital):
|
|
if "inputs" not in group:
|
|
return bindings
|
|
for i in group["inputs"]:
|
|
for act in group["inputs"][i]:
|
|
for fp in group["inputs"][i][act]:
|
|
for bd in group["inputs"][i][act][fp]:
|
|
for bbd in group["inputs"][i][act][fp][bd]:
|
|
if bbd.lower() == 'binding':
|
|
x = group["inputs"][i][act][fp][bd].get_all_for(bbd)
|
|
for ss in x:
|
|
st = ss.split()
|
|
supported_binding = False
|
|
if st[0].lower() == 'game_action':
|
|
supported_binding = True
|
|
if st[2][-1] == ",":
|
|
action_name = st[2][:-1]
|
|
else:
|
|
action_name = st[2][:]
|
|
elif st[0].lower() == 'xinput_button':
|
|
supported_binding = True
|
|
if st[1][-1] == ",":
|
|
action_name = st[1][:-1]
|
|
else:
|
|
action_name = st[1][:]
|
|
|
|
if supported_binding:
|
|
if force_binding is None:
|
|
binding = keymap.get(i.lower(), None)
|
|
else:
|
|
binding = force_binding
|
|
|
|
if binding:
|
|
if action_name in bindings:
|
|
if binding not in bindings[action_name]:
|
|
bindings[action_name].append(binding)
|
|
else:
|
|
bindings[action_name] = [binding]
|
|
else:
|
|
print(f"[X] missing keymap for {i}")
|
|
return bindings
|
|
|
|
|
|
def generate_controller_config(controller_vdf, config_dir):
|
|
d = vdf.loads(controller_vdf, mapper=vdf.VDFDict, merge_duplicate_keys=False)
|
|
|
|
controller_mappings = d["controller_mappings"]
|
|
|
|
groups = controller_mappings.get_all_for("group")
|
|
groups_byid = {}
|
|
for g in groups:
|
|
groups_byid[g["id"]] = g
|
|
|
|
actions = controller_mappings.get_all_for("actions")
|
|
action_list = []
|
|
for a in actions:
|
|
for k in a:
|
|
action_list.append(k)
|
|
|
|
presets = controller_mappings.get_all_for("preset")
|
|
all_bindings = {}
|
|
for p in presets:
|
|
name = p["name"]
|
|
if (name not in action_list) and name.lower() != 'default':
|
|
continue
|
|
group_bindings = p["group_source_bindings"]
|
|
bindings = {}
|
|
for number in group_bindings:
|
|
s = group_bindings[number].split()
|
|
if s[1].lower() != "active":
|
|
continue
|
|
|
|
#print(s)
|
|
if s[0].lower() in ["switch", "button_diamond", "dpad"]:
|
|
group = groups_byid[number]
|
|
#print(group)
|
|
bindings = add_input_bindings(group, bindings)
|
|
|
|
if s[0].lower() in ["left_trigger", "right_trigger"]:
|
|
group = groups_byid[number]
|
|
if group["mode"].lower() == "trigger":
|
|
for g in group:
|
|
if g.lower() == "gameactions":
|
|
#print(group)
|
|
action_name = group["gameactions"][name]
|
|
if s[0].lower() == "left_trigger":
|
|
binding = "LTRIGGER"
|
|
else:
|
|
binding = "RTRIGGER"
|
|
if action_name in bindings:
|
|
if binding not in bindings[action_name] and (binding + "=trigger") not in bindings[action_name]:
|
|
bindings[action_name].insert(0, binding)
|
|
else:
|
|
bindings[action_name] = [binding + "=trigger"]
|
|
if g.lower() == "inputs":
|
|
if s[0].lower() == "left_trigger":
|
|
binding = "DLTRIGGER"
|
|
else:
|
|
binding = "DRTRIGGER"
|
|
bindings = add_input_bindings(group, bindings, binding)
|
|
|
|
else:
|
|
print("unhandled trigger mode", group["mode"])
|
|
|
|
if s[0].lower() in ["joystick", "right_joystick", "dpad"]:
|
|
group = groups_byid[number]
|
|
if group["mode"].lower() == "joystick_move":
|
|
for g in group:
|
|
if g.lower() == "gameactions":
|
|
#print(group)
|
|
action_name = group["gameactions"][name]
|
|
if s[0].lower() == "joystick":
|
|
binding = "LJOY"
|
|
elif s[0].lower() == "right_joystick":
|
|
binding = "RJOY"
|
|
elif s[0].lower() == "dpad":
|
|
binding = "DPAD"
|
|
else:
|
|
print("could not handle", s[0])
|
|
if action_name in bindings:
|
|
if binding not in bindings[action_name] and (binding + "=joystick_move") not in bindings[action_name]:
|
|
bindings[action_name].insert(0, binding)
|
|
else:
|
|
bindings[action_name] = [binding + "=joystick_move"]
|
|
if g.lower() == "inputs":
|
|
if s[0].lower() == "joystick":
|
|
binding = "LSTICK"
|
|
else:
|
|
binding = "RSTICK"
|
|
bindings = add_input_bindings(group, bindings, binding)
|
|
|
|
elif group["mode"].lower() == "dpad":
|
|
if s[0].lower() == "joystick":
|
|
binding_map = {"dpad_north":"DLJOYUP", "dpad_south": "DLJOYDOWN", "dpad_west": "DLJOYLEFT", "dpad_east": "DLJOYRIGHT", "click": "LSTICK"}
|
|
bindings = add_input_bindings(group, bindings, keymap=binding_map)
|
|
elif s[0].lower() == "right_joystick":
|
|
binding_map = {"dpad_north":"DRJOYUP", "dpad_south": "DRJOYDOWN", "dpad_west": "DRJOYLEFT", "dpad_east": "DRJOYRIGHT", "click": "RSTICK"}
|
|
bindings = add_input_bindings(group, bindings, keymap=binding_map)
|
|
else:
|
|
if s[0].lower() != "dpad":
|
|
print("no pad", s[0])
|
|
else:
|
|
print("unhandled joy mode", group["mode"])
|
|
|
|
all_bindings[name] = bindings
|
|
|
|
#print(controller_mappings["preset"][(0, "group_source_bindings")])
|
|
|
|
#print(all_bindings)
|
|
|
|
if all_bindings:
|
|
if not os.path.exists(config_dir):
|
|
os.makedirs(config_dir)
|
|
|
|
for k in all_bindings:
|
|
with open(os.path.join(config_dir, f'{k}.txt'), 'w', encoding='utf-8') as f:
|
|
for b in all_bindings[k]:
|
|
f.write(f"{b}=" + ','.join(all_bindings[k][b]) + "\n")
|
|
|
|
|
|
def help():
|
|
exe_name = os.path.basename(sys.argv[0])
|
|
print(f"\nUsage: {exe_name} xbox_controller_config.vdf [xbox360_controller_config.vdf] ... ")
|
|
print(f" Example: {exe_name} xbox_controller_config.vdf")
|
|
print(f" Example: {exe_name} xboxone_controller.vdf xbox360_controller.vdf")
|
|
print("\nAt least 1 .vdf file must be provided\n")
|
|
|
|
if __name__ == '__main__':
|
|
if len(sys.argv) < 2:
|
|
help()
|
|
sys.exit(1)
|
|
|
|
for vdf_file in sys.argv[1:]:
|
|
try:
|
|
print(f"parsing controller file '{vdf_file}'")
|
|
t = ''
|
|
with open(vdf_file, 'rb') as f:
|
|
t = f.read().decode('utf-8')
|
|
if t:
|
|
filename = os.path.basename(vdf_file)
|
|
outdir = os.path.join(f"{filename}_config", "steam_settings", "controller")
|
|
print(f"output dir: '{outdir}'")
|
|
generate_controller_config(t, outdir)
|
|
else:
|
|
print("[X] couldn't load file", file=sys.stderr)
|
|
|
|
print('**********************************\n')
|
|
except Exception as e:
|
|
print("Unexpected error:")
|
|
print(e)
|
|
print("-----------------------")
|
|
for line in traceback.format_exception(e):
|
|
print(line)
|
|
print('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n')
|
|
|
|
sys.exit(0)
|