feat: add pixelated app icons and remove devkit prefix from steam shortcuts

This commit is contained in:
Pixelplanet committed 2026-10-18 09:29:59 +02:00
1 parent 7bf367419f
commit aa896397fe
14 files changed
+93 -8

No files matched your search

+1 -2
View File
@@ -259,8 +259,7 @@ choice, and troubleshooting). In short, after a one-time Developer-Mode pairing:
# override the target with --host steamos@<ip> or FRAME_HOST
```
Either way the app appears in **Steam ▸ Library ▸ Non-Steam** as *Devkit Game:
PixelVRPlayer*. To run it manually over SSH for debugging:
Either way the app appears in **Steam ▸ Library ▸ Non-Steam** as **Pixel VR Player**. To run it manually over SSH for debugging:
```bash
ssh steamos@frame '~/devkit-game/PixelVRPlayer/launch.sh /path/to/video.mp4'
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

+1 -2
View File
@@ -94,8 +94,7 @@ All three methods below share the same setup. Do this once.
- **Easiest to iterate:** Option B (one command builds nothing you didn't ask for
and launches in the headset).
They all end up in the same place: *Steam ▸ Library ▸ Non-Steam ▸ **Devkit Game:
PixelVRPlayer***.
They all end up in the same place: *Steam ▸ Library ▸ Non-Steam ▸ **Pixel VR Player***.
---
+66 -2
View File
@@ -127,7 +127,7 @@ def main() -> int:
'mkdir -p "$target/shaders"; printf %s "$target"'
)
# 2. Copy binary, shaders and the direct-run helper.
# 2. Copy binary, shaders, launcher, and icon.
print("Copying binary ...")
scp([str(binary)], f"{REMOTE_DIR}/pixelvr")
if shaders:
@@ -136,6 +136,9 @@ def main() -> int:
launch_helper = PROJECT_ROOT / "tools" / "launch.sh"
if launch_helper.is_file():
scp([str(launch_helper)], f"{REMOTE_DIR}/launch.sh")
icon_file = PROJECT_ROOT / "assets" / "icon.png"
if icon_file.is_file():
scp([str(icon_file)], f"{REMOTE_DIR}/icon.png")
# 3. Register the Non-Steam shortcut (runs on the host, not in Sniper).
request = {
@@ -165,6 +168,67 @@ def main() -> int:
if isinstance(response, dict) and response.get("error"):
raise RuntimeError(f"shortcut registration failed: {response['error']}")
# 3b. Sanitize shortcuts.vdf to remove the 'Devkit Game: ' prefix and set icon.
sanitize_script = (
"import glob, os, struct, shutil\n"
"OBJ, STR, INT, U64, END = 0, 1, 2, 7, 8\n"
"def read_cstr(buf, pos):\n"
" end = buf.find(b'\\0', pos)\n"
" return buf[pos:end].decode('utf-8', 'surrogateescape'), end + 1\n"
"def parse_obj(buf, pos):\n"
" entries = {}\n"
" while pos < len(buf):\n"
" kind = buf[pos]\n"
" if kind in (END, 0x0B): return entries, pos + 1\n"
" key, pos = read_cstr(buf, pos + 1)\n"
" if kind == OBJ: value, pos = parse_obj(buf, pos)\n"
" elif kind == STR: value, pos = read_cstr(buf, pos)\n"
" elif kind == INT: value = struct.unpack_from('<i', buf, pos)[0]; pos += 4\n"
" elif kind == U64: value = struct.unpack_from('<Q', buf, pos)[0]; pos += 8\n"
" else: break\n"
" entries[key] = [kind, value]\n"
" return entries, pos\n"
"def dump(entries):\n"
" out = bytearray()\n"
" for key, (kind, value) in entries.items():\n"
" kb = key.encode('utf-8', 'surrogateescape')\n"
" if kind == OBJ: out += bytes([OBJ]) + kb + b'\\0' + dump(value) + bytes([END])\n"
" elif kind == STR: out += bytes([STR]) + kb + b'\\0' + value.encode('utf-8', 'surrogateescape') + b'\\0'\n"
" elif kind == INT: out += bytes([INT]) + kb + b'\\0' + struct.pack('<i', value)\n"
" elif kind == U64: out += bytes([U64]) + kb + b'\\0' + struct.pack('<Q', value)\n"
" return bytes(out)\n"
"for vdf in glob.glob(os.path.expanduser('~/.steam/steam/userdata/*/config/shortcuts.vdf')):\n"
" try:\n"
" with open(vdf, 'rb') as f: data = f.read()\n"
" if not data or data[0] != OBJ: continue\n"
" key, pos = read_cstr(data, 1)\n"
" s_dict, _ = parse_obj(data, pos)\n"
" mod = False\n"
" for k, v in s_dict.items():\n"
" if isinstance(v, list) and v[0] == OBJ:\n"
" e = v[1]\n"
" name = e.get('AppName', [STR, ''])[1]\n"
" if 'Pixel' in name:\n"
" e['AppName'] = [STR, 'Pixel VR Player']\n"
" e['Devkit'] = [INT, 0]\n"
" e['DevkitGameID'] = [STR, '']\n"
" icon_p = os.path.expanduser('~/" + REMOTE_DIR + "/icon.png')\n"
" if os.path.isfile(icon_p):\n"
" e['icon'] = [STR, icon_p]\n"
" grid = os.path.join(os.path.dirname(os.path.dirname(vdf)), 'config', 'grid')\n"
" os.makedirs(grid, exist_ok=True)\n"
" raw_id = e.get('appid', [INT, 0])[1] & 0xFFFFFFFF\n"
" shutil.copyfile(icon_p, os.path.join(grid, f'{raw_id}.png'))\n"
" mod = True\n"
" if mod:\n"
" tmp = vdf + '.tmp'\n"
" with open(tmp, 'wb') as f: f.write(dump({key: [OBJ, s_dict]}) + bytes([END]))\n"
" os.replace(tmp, vdf)\n"
" except Exception:\n"
" pass\n"
)
ssh(f"python3 -c {shlex.quote(sanitize_script)}")
# 4. Optionally launch it in the headset.
if args.launch:
print("Launching in the headset ...")
@@ -184,7 +248,7 @@ def main() -> int:
print(f"Deployed to {host}:~/{REMOTE_DIR}")
if player_args:
print(" argv:", " ".join(["./pixelvr", *player_args]))
print(f" Launch from Steam > Library > Non-Steam > 'Devkit Game: {GAME}'")
print(" Launch from Steam > Library > Non-Steam > 'Pixel VR Player'")
print(f" Or over SSH: ssh {host} '{REMOTE_DIR}/launch.sh <video>'")
return 0
+22 -2
View File
@@ -230,7 +230,8 @@ def find(shortcuts, name, exe):
continue
stored_exe = entry.get("Exe", [STR, ""])[1].strip('"')
stored_name = entry.get("AppName", [STR, ""])[1]
if (exe and stored_exe == exe) or stored_name == name:
devkit_id = entry.get("DevkitGameID", [STR, ""])[1]
if (exe and stored_exe == exe) or stored_name == name or stored_name in ("Devkit Game: PixelVRPlayer", "Devkit Game: Pixel VR Player") or devkit_id == "PixelVRPlayer":
return key, entry
return None, None
@@ -276,11 +277,12 @@ def main():
shortcuts[str(index)] = [OBJ, entry]
if "appid" not in entry:
entry["appid"] = [INT, to_i32(app_id(quoted_exe, name))]
icon_path = os.path.join(start_dir, "icon.png") if os.path.isfile(os.path.join(start_dir, "icon.png")) else ""
for field, value in (
("AppName", [STR, name]),
("Exe", [STR, quoted_exe]),
("StartDir", [STR, '"%s"' % start_dir]),
("icon", [STR, ""]),
("icon", [STR, icon_path]),
("ShortcutPath", [STR, ""]),
("LaunchOptions", [STR, ""]),
("IsHidden", [INT, 0]),
@@ -295,6 +297,17 @@ def main():
):
entry[field] = value
entry.setdefault("tags", [OBJ, {}])
if icon_path and os.path.isfile(icon_path):
try:
import shutil
steam_user_dir = os.path.dirname(os.path.dirname(path))
grid_dir = os.path.join(steam_user_dir, "config", "grid")
os.makedirs(grid_dir, exist_ok=True)
raw_appid = entry["appid"][1] & 0xFFFFFFFF
shutil.copyfile(icon_path, os.path.join(grid_dir, "%d_icon.png" % raw_appid))
shutil.copyfile(icon_path, os.path.join(grid_dir, "%d.png" % raw_appid))
except Exception:
pass
print("%s '%s' (%d shortcut(s) in the library)" % (
"added" if created else "updated", name, len(shortcuts)))
@@ -509,6 +522,13 @@ if [ -f "$srcdir/VERSION" ]; then
elif [ -n "$VERSION" ]; then
printf '%s\n' "$VERSION" > "$INSTALL_DIR/VERSION"
fi
if [ -f "$srcdir/icon.png" ]; then
cp "$srcdir/icon.png" "$INSTALL_DIR/icon.png"
elif [ -n "$script_dir" ] && [ -f "$script_dir/icon.png" ]; then
cp "$script_dir/icon.png" "$INSTALL_DIR/icon.png"
elif [ -f "assets/icon.png" ]; then
cp "assets/icon.png" "$INSTALL_DIR/icon.png"
fi
ok "$(ls -1 "$INSTALL_DIR/shaders" | wc -l | tr -d ' ') shaders, $(du -h "$INSTALL_DIR/pixelvr" 2>/dev/null | cut -f1) binary"
missing_libs=""
+3
View File
@@ -40,6 +40,9 @@ cp tools/install.sh "${stage}/PixelVRPlayer/install.sh"
if [[ -f "tools/Install Pixel VR Player.desktop" ]]; then
cp "tools/Install Pixel VR Player.desktop" "${stage}/PixelVRPlayer/Install Pixel VR Player.desktop"
fi
if [[ -f "assets/icon.png" ]]; then
cp "assets/icon.png" "${stage}/PixelVRPlayer/icon.png"
fi
if [[ -n "${VERSION}" ]]; then
printf '%s\n' "${VERSION}" > "${stage}/PixelVRPlayer/VERSION"
fi