Files
obsidian-vault/family/how-to/htpc-steam-nonsteam-shortcuts.md
T

3.4 KiB

Non-Steam Shortcuts через Binary VDF

Формат файла

Shortcuts хранятся в бинарном VDF: ~/.steam/steam/userdata/147839491/config/shortcuts.vdf

Это НЕ текстовый файл — редактировать через обычную замену строк нельзя, потому что:

  • Каждое поле хранится с длиной строки
  • Замена строки на другую длины ломает весь файл
  • Steam после запуска может перезаписать сломанный файл, удалив все non-Steam игры

Безопасный способ — Python

import os, struct

vdf_path = os.path.expanduser('~/.steam/steam/userdata/147839491/config/shortcuts.vdf')

# 1. Всегда делать бэкап
import shutil
shutil.copy2(vdf_path, vdf_path + '.bak')

with open(vdf_path, 'rb') as f:
    data = bytearray(f.read())

# Helper: string field
def sf(name, value):
    nb = name.encode() + b'\x00'
    vb = value.encode() + b'\x00'
    return bytes([0x01, len(nb)]) + nb + bytes([len(vb)]) + vb

# Helper: int field
def zf(name, value):
    nb = name.encode() + b'\x00'
    vb = struct.pack('<I', value)
    return bytes([0x02, len(nb)]) + nb + bytes([len(vb)]) + vb

# Build the entire entry with all fields Steam expects
entry = b''

# appid (int field, type 0x02)
appid_n = b'appid\x00'
appid_v = struct.pack('<I', APPID)  # unsigned 32-bit int
entry += bytes([0x02, len(appid_n)]) + appid_n + bytes([len(appid_v)]) + appid_v

entry += sf('AppName', 'Name in Library')
entry += sf('Exe', '/path/to/game.exe')
entry += sf('StartDir', '/path/to/')
entry += sf('icon', '')
entry += sf('ShortcutPath', '')
entry += sf('LaunchOptions', '')

# Boolean fields (int, 0 or 1)
entry += zf('IsHidden', 0)
entry += zf('AllowDesktopConfig', 1)
entry += zf('AllowOverlay', 1)
entry += zf('OpenVR', 0)
entry += zf('Devkit', 0)

entry += sf('DevkitGameID', '')
entry += zf('DevkitOverrideAppID', 0)
entry += zf('LastPlayTime', 0)

entry += sf('FlatpakAppID', '')
entry += sf('sortas', '')

# tags array (must end with \x08\x08\x08)
tags_n = b'tags\x00'
entry += bytes([0x00, len(tags_n)]) + tags_n + b'\x08'
entry += b'\x08\x08\x08'

Добавление нового shortcut (к существующим)

  1. Найти начало и конец последней записи
  2. Вставить новую запись перед закрывающими байтами файла
  3. Записать файл целиком

Структура файла: \x00shortcuts\x00\x00 + \x30\x00 + [entry1] + [entry2] + ... + \x08\x08

Перезагрузка Steam без рестарта

DISPLAY=:0 steam 'steam://reloadshortcuts'

Важно: если Steam уже переписал сломанный файл — изменения не откатятся. Нужно восстанавливать из бэкапа, а потом форсить reload.

Важно

  • Никогда не делать replace строк разной длины
  • Всегда держать бэкап
  • Если non-Steam игры пропали — восстановить из бэкапа, сделать reloadshortcuts
  • AppID можно взять любой unsigned 32-bit (лучше > 2000000000 чтобы не конфликтовать с реальными Steam AppID)