2

Similar to How do I find the ID for a game on Steam? but this is about non-steam games (shortcuts).

I'm trying to figure out what to name my custom artwork for non-steam games to get steam to recognize them.

  • I know they go in this folder: steam/userdata/<userid>/config/grid
  • I know there are three: <id>_logo.png, <id>_hero.jpg, <id>p.jpg,

I know I can look in localconfig.vdf to find the <userid> value, but I don't know how to find the <id> value.

By adding custom art through the steam client, I see the correct value is 2853772086. However, I want to do this programmatically. How do I compute this value?

That doesn't match the index 14 nor the appid -1441195210 (signed or unsigned) in the shortcuts.vdf:

 '14': {'AllowDesktopConfig': 1,
        'AllowOverlay': 1,
        'Devkit': 0,
        'DevkitGameID': '',
        'IsHidden': 0,
        'LastPlayTime': 0,
        'LaunchOptions': '',
        'ShortcutPath': '',
        'StartDir': 'c:\\libraries\\itch\\baba',
        'appid': -1441195210,
        'appname': 'Baba Is You',
        'exe': 'c:\\libraries\\itch\\baba\\Baba Is You\\Baba Is You.exe',
        'icon': 'c:\\libraries\\itch\\baba\\Baba Is You\\Baba Is You.exe',
        'openvr': 0,
        'tags': {'0': 'steamsync'}},

The game's appid on steam 736260 so (unsurprisingly) it's not related to that either.

3

Steam uses two different ids used to load art for non-steam shortcuts.

You can ignore the Big Picture specific logic and set the icon as your desired Big Picture art but that icon will also be used in Steam desktop client.

Steam Desktop

steamgrid figured out how to get a normal shortcut id. They describe the solution as "crc32(exe + appname) + "02000000", using IEEE standard polynomials" and using exe and appname from shortcuts.vdf.

For some reason, steamgrid refers it as the LegacyID, but this is the format for art for steam's redesigned client. This id seems to be unrelated to the desktop shortcut id (which is also used in screenshots.vdf) and unrelated to images in Big Picture mode (which uses the icon field in shortcuts.vdf).

UWPHook as a C# implementation to find the id and separate code for the paths.

import binascii

def get_steam_shortcut_id(exe, appname):
    """Get id for non-steam shortcut.

    get_steam_shortcut_id(str, str) -> int
    """
    grid = Path(f"{steam_path}/userdata/{steamid}/config/grid")
    unique_id = ''.join([exe, appname])
    id_int = binascii.crc32(str.encode(unique_id)) | 0x80000000
    return id_int

Big Picture

scottrice/Ice steamgrid figured out how to get a Big Picture shortcut id. They explain:

Calculates the filename for a given shortcut. This filename is a 64bit integer, where the first 32bits are a CRC32 based off of the name and target (with the added condition that the first bit is always high), and the last 32bits are 0x02000000.

The implementation looks roughly like this (requires pycrc):

# Copyright (c) 2012-2013, 2013 Scott Rice
# All rights reserved. MIT License
import pycrc.algorithms as crc
def get_bigpicture_shortcut_id(exe, appname):
    algorithm = crc.Crc(width = 32, poly = 0x04C11DB7, reflect_in = True, xor_in = 0xffffffff, reflect_out = True, xor_out = 0xffffffff)
    input_string = ''.join([exe,appname])
    top_32 = algorithm.bit_by_bit(input_string) | 0x80000000
    full_64 = (top_32 << 32) | 0x02000000
    return str(full_64)

See the original for more details/comments.

You can see that this is very similar to the normal shortcut id except it has some extra lower bits.

Bringing it Together

We can put it all together to get the locations for all the art like so:

from pathlib import Path
import binascii

def get_steam_shortcut_id(exe, appname):
    """Get id for non-steam shortcut.

    get_steam_shortcut_id(str, str) -> str
    """
    unique_id = ''.join([exe, appname])
    id_int = binascii.crc32(str.encode(unique_id)) | 0x80000000
    return id_int


def get_grid_art_destinations(steam_path, steamid, exe, appname):
    """Get filepaths for the grid images for the input shortcut.

    get_grid_art_destinations(str, str, str, str) -> dict[str,Path]
    """
    grid = Path(f"{steam_path}/userdata/{steamid}/config/grid")
    shortcut = get_steam_shortcut_id(exe, appname)
    bp_shortcut = (shortcut << 32) | 0x02000000
    return {
        'boxart': grid / f"{shortcut}p.jpg",
        'hero':   grid / f"{shortcut}_hero.jpg",
        'logo':   grid / f"{shortcut}_logo.png",
        '10foot': grid / f"{bp_shortcut}.png",
    }

import pprint
pprint.pprint(get_grid_art_destinations("C:/Program Files (x86)/Steam", '00000000', 'c:\\libraries\\itch\\baba\\Baba Is You\\Baba Is You.exe','Baba Is You'))

Here's a complete python implementation.

0

There are a couple open source solutions that do this; UWPHook and Ice are some examples. Both are using CRC algorithms with a combination of target and app name. These don't seem to be the complete solution though.

For instance if you add a shortcut, remove it and then re-add it by following these steps, you will find that when adding images for the re-added shortcut that the images will have different names/id under ../steam/userdata/<userid>/config/grid for the <id>.

  1. Add a steam shortcut
  2. Provide the new shortcut with custom artwork
  3. Check ../steam/userdata/<userid>/config/grid for the <id>
  4. Remove the shortcut from Steam
  5. Repeat 1-3 and note the different <id>

You can also try adding a shortcut to steam, giving it custom artwork, then add programs with UWPHook and notice that when you restart steam, the shorcut you manually added no longer has any custom artwork even though it's target and app name are the same.

1
  • If you backup your shortcuts.vdf and follow those steps, is the new shortcuts.vdf different from the backed up one? I wonder if something is subtly changing the shortcut.
    – idbrii
    Jul 10 at 1:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.