6.6 KiB
Non-Steam Shortcuts через VDF
Главное правило
Steam должен быть выключен перед записью shortcuts.vdf. Если Steam работает — он перезапишет файл из памяти при следующем запуске.
Остановка Steam (Bazzite game session)
systemctl --user stop gamescope-session-plus@steam.service
sleep 2
systemctl --user is-active gamescope-session-plus@steam.service # должен вернуть "inactive"
# правишь VDF
systemctl --user start gamescope-session-plus@steam.service
Если после stop Steam всё ещё активен — повторить.
Процедура (один bash-скрипт)
Один скрипт на HTPC: останавливает Steam → делает бэкап → редактирует VDF → запускает Steam.
Использовать модуль vdf (установлен на HTPC через pip). Никогда не редактировать бинарный VDF через ручную сборку байтов или замену строк — это ломает файл.
#!/bin/bash
set -e
# 1. Остановить Steam
systemctl --user stop gamescope-session-plus@steam.service
sleep 2
# 2. Бэкап
cp ~/.steam/steam/userdata/147839491/config/shortcuts.vdf{,.bak}
# 3. Редактировать VDF (скрипт лежит рядом)
python3 /path/to/edit_vdf.py
# 4. Запустить Steam
systemctl --user start gamescope-session-plus@steam.service
Python-скрипт (edit_vdf.py):
import os, vdf, shutil, binascii, struct
vdf_path = os.path.expanduser('~/.steam/steam/userdata/147839491/config/shortcuts.vdf')
with open(vdf_path, 'rb') as f:
data = vdf.binary_load(f)
shortcuts = data.get('shortcuts', {})
def compute_appid(name, exe):
key = exe + name
top = binascii.crc32(key.encode('utf-8')) | 0x80000000
return struct.unpack('i', struct.pack('I', top))[0]
next_idx = str(len(shortcuts))
shortcuts[next_idx] = {
'AppName': 'Game Name',
'Exe': '/home/bazzite/Emulation/tools/launchers/ryujinx.sh',
'StartDir': '/home/bazzite/Emulation/tools/launchers',
'LaunchOptions': '/home/bazzite/Emulation/roms/switch/animal_crossing.nsp',
'appid': compute_appid('Game Name', '/home/bazzite/Emulation/tools/launchers/ryujinx.sh'),
'IsHidden': 0,
'AllowDesktopConfig': 1,
'AllowOverlay': 1,
'OpenVR': 0,
'Devkit': 0,
'DevkitGameID': '',
'DevkitOverrideAppID': 0,
'LastPlayTime': 0,
'FlatpakAppID': '',
'sortas': '',
'tags': {},
}
data['shortcuts'] = shortcuts
with open(vdf_path, 'wb') as f:
vdf.binary_dump(data, f)
Скрипты на HTPC загружать через scp, не через heredoc.
CompatToolMapping (Proton) в config.vdf
После добавления shortcut нужно прописать Proton в текстовом config.vdf:
import vdf
CONFIG_PATH = os.path.expanduser('~/.local/share/Steam/config/config.vdf')
with open(CONFIG_PATH, 'r') as f:
config = vdf.load(f)
compat_map = config['InstallConfigStore']['Software']['Valve']['Steam'].setdefault('CompatToolMapping', {})
compat_map[str(appid_signed)] = {
'name': 'GE-Proton10-34', # или 'proton_experimental'
'config': '',
'Priority': '250',
}
with open(CONFIG_PATH, 'w') as f:
vdf.dump(config, f)
Полный скилл
Вся процедура (shortcuts + Proton + artwork) описана в скилле steam-emulator-shortcuts. Смотреть там.
Бэкап
cp ~/.steam/steam/userdata/*/config/shortcuts.vdf{,.bak}
Автоматический бэкап shortcuts.vdf делается ежедневно скриптом backup-saves.sh на HTPC, версии хранятся в /run/media/bazzite/Data/backups/saves/shortcuts/ (последние 30 копий).
Перезагрузка Steam
После записи VDF — перезапустить Steam, чтобы он подхватил изменения.
Wide Steam Grid Posters — Порядок действий
Перед остановкой Steam — сначала скачать все постеры. Так как Steam не нужен для скачивания.
Постеры для всех форматов
При добавлении новой не-Steam игры — сразу скачивай все 4 формата:
| Размер | Формат файла | Назначение |
|---|---|---|
| 920×430 | {unsigned_appid}.png |
Wide — основная карточка в библиотеке |
| 600×900 | {unsigned_appid}p.png |
Poster — вертикальный, при наведении |
| 1920×620 | {unsigned_appid}_hero.png |
Hero — фон на странице игры |
| 1200×351 | {unsigned_appid}_logo.png |
Логотип на hero |
Unsigned appid = signed_appid & 0xFFFFFFFF. Пример: -1321720074 → 2973247222.
→ Подробно: htpc-steam-nonsteam-shortcuts
Процедура (как делал Whale)
-
Найти постеры на SteamGridDB — зайти на
https://www.steamgriddb.com/game/<ID>, отфильтровать по 920×430.- Для новых игр: поискать
<игра> site:steamgriddb.com - Wide grids часто меньше по количеству чем posters (600×900), их ищем в секции Grids → фильтр
Dimensions: 920×430
- Для новых игр: поискать
-
Получить прямую ссылку CDN — thumbnails на странице grid'a ведут на
cdn2.steamgriddb.com/thumb/<hash>.jpg, а полный файл лежит поcdn2.steamgriddb.com/grid/<hash>.png. -
Скачать локально:
curl -s -o /tmp/<appid>.png "https://cdn2.steamgriddb.com/grid/<hash>.png" -
Закинуть на HTPC через scp в
/tmp/:scp /tmp/<appid>.png bazzite@192.168.1.86:/tmp/<appid>.png -
Скопировать в grid-директорию Steam:
ssh bazzite@192.168.1.86 cp /tmp/<appid>.png ~/.steam/steam/userdata/147839491/config/grid/<appid>.png -
Перезапустить Steam (Steam перечитывает grid-файлы свежими при старте, но часто подхватывает и без перезапуска):
systemctl --user stop gamescope-session-plus@steam.service systemctl --user start gamescope-session-plus@steam.service
SteamGridDB ключ API
5f0a7cb3366dede2c10860a95795ce60 — для программного доступа.