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

6.4 KiB
Raw Blame History

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 всё ещё активен — повторить.

Единственный правильный способ — vdf.binary_load

Процедура (один py-скрипт, с бэкапом):

  1. Остановить Steam
  2. Сделать бэкап shortcuts.vdf
  3. Отредактировать VDF
  4. Запустить Steam

Использовать модуль vdf (установлен на HTPC через pip). Никогда не редактировать бинарный VDF через ручную сборку байтов или замену строк — это ломает файл.

import os, vdf, shutil, binascii, struct

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

# 1. Бэкап
shutil.copy2(vdf_path, vdf_path + '.bak')

# 2. Загрузить существующий
with open(vdf_path, 'rb') as f:
    data = vdf.binary_load(f)

shortcuts = data.get('shortcuts', {})

# 3. Вычислить appid (алгоритм Steam)
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]

# 4. Создать entry
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': {},
}

# 5. Записать
data['shortcuts'] = shortcuts
with open(vdf_path, 'wb') as f:
    vdf.binary_dump(data, f)

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. Пример: -13217200742973247222.

→ Подробно: htpc-steam-nonsteam-shortcuts

Процедура (как делал Whale)

  1. Найти постеры на SteamGridDB — зайти на https://www.steamgriddb.com/game/<ID>, отфильтровать по 920×430.

    • Для новых игр: поискать <игра> site:steamgriddb.com
    • Wide grids часто меньше по количеству чем posters (600×900), их ищем в секции Grids → фильтр Dimensions: 920×430
  2. Получить прямую ссылку CDN — thumbnails на странице grid'a ведут на cdn2.steamgriddb.com/thumb/<hash>.jpg, а полный файл лежит по cdn2.steamgriddb.com/grid/<hash>.png.

  3. Скачать локально:

    curl -s -o /tmp/<appid>.png "https://cdn2.steamgriddb.com/grid/<hash>.png"
    
  4. Закинуть на HTPC через scp в /tmp/:

    scp /tmp/<appid>.png bazzite@192.168.1.86:/tmp/<appid>.png
    
  5. Скопировать в grid-директорию Steam:

    ssh bazzite@192.168.1.86
    cp /tmp/<appid>.png ~/.steam/steam/userdata/147839491/config/grid/<appid>.png
    
  6. Перезапустить Steam (Steam перечитывает grid-файлы свежими при старте, но часто подхватывает и без перезапуска):

    systemctl --user stop gamescope-session-plus@steam.service
    systemctl --user start gamescope-session-plus@steam.service
    

SteamGridDB ключ API

5f0a7cb3366dede2c10860a95795ce60 — для программного доступа.