<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>steamdeck on foosel.net</title><link>https://foosel.net/tags/steamdeck/</link><description>Recent content in steamdeck on foosel.net</description><generator>Hugo</generator><language>en-us</language><copyright>Gina Häußge (foosel)</copyright><lastBuildDate>Tue, 25 Mar 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://foosel.net/tags/steamdeck/feed.xml" rel="self" type="application/rss+xml"/><item><title>How to automatically sync screenshots from the Steamdeck to Immich</title><link>https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-immich/</link><pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate><guid>https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-immich/</guid><description>&lt;p&gt;As part of &lt;a href="https://chaos.social/@foosel/114105591362840338"&gt;my ongoing effort to reduce my dependency on US services&lt;/a&gt;, I just moved my photos
from Google Photos to a self-hosted &lt;a href="https://immich.app/"&gt;immich&lt;/a&gt; instance (which I btw can only recommend so far).&lt;/p&gt;
&lt;p&gt;You might remember from &lt;a href="https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/"&gt;a previous TIL&lt;/a&gt;
that I had my Steamdeck configured to push my screenshots into a custom album on Google Photos. Obviously I had to change that now as well,
but sadly couldn&amp;rsquo;t use the existing &lt;a href="https://rclone.org/"&gt;rclone&lt;/a&gt;-based setup for it.&lt;/p&gt;</description><content:encoded><![CDATA[<p>As part of <a href="https://chaos.social/@foosel/114105591362840338">my ongoing effort to reduce my dependency on US services</a>, I just moved my photos
from Google Photos to a self-hosted <a href="https://immich.app/">immich</a> instance (which I btw can only recommend so far).</p>
<p>You might remember from <a href="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/">a previous TIL</a>
that I had my Steamdeck configured to push my screenshots into a custom album on Google Photos. Obviously I had to change that now as well,
but sadly couldn&rsquo;t use the existing <a href="https://rclone.org/">rclone</a>-based setup for it.</p>
<p>My first idea was to utilize <a href="https://github.com/simulot/immich-go">immich-go</a>, as I have just successfully used that for the
three day long import of over 50000 pictures from my Google Photos takeout into immich. But that turned out to not be the right tool here: in order to not even try to
upload already existing files it will fetch an asset list from immich first, and while that really improves performance for large batch imports,
it takes way too long for uploading a single new screenshot.</p>
<p>So instead I went with something self-built which utilizes <a href="https://immich.app/docs/api/">immich&rsquo;s API</a>.</p>
<h2 id="a-custom-upload-script">A custom upload script</h2>
<p>The first part is this little bash script that will take a file as input, upload it to a pre-configured immich instance and also add it to a
pre-defined album (which already has to exist). This lives in <code>~/.local/bin/immich-upload.sh</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>set -e
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>IMMICH_SERVER<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://immich.example.com&#34;</span>
</span></span><span style="display:flex;"><span>IMMICH_KEY<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;your api key goes here&#34;</span>
</span></span><span style="display:flex;"><span>IMMICH_ALBUM<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;your album id goes here&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>INPUT<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$INPUT<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;immich-upload.sh &lt;file&gt;&#34;</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>file_modified<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>stat -c %Y <span style="color:#e6db74">&#34;</span>$INPUT<span style="color:#e6db74">&#34;</span> | date --iso-8601<span style="color:#f92672">=</span>seconds<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>name<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>basename <span style="color:#e6db74">&#34;</span>$INPUT<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ---</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Uploading </span>$INPUT<span style="color:#e6db74"> to immich...&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>upload<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>curl -sL --request POST <span style="color:#e6db74">&#34;</span>$IMMICH_SERVER<span style="color:#e6db74">/api/assets&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Content-Type: multipart/form-data&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Accept: application/json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;X-API-Key: </span>$IMMICH_KEY<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;deviceId=\&#34;curl/steamdeck\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;deviceAssetId=\&#34;</span>$name<span style="color:#e6db74">-</span>$file_modified<span style="color:#e6db74">\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;fileCreatedAt=\&#34;</span>$file_modified<span style="color:#e6db74">\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;fileModifiedAt=\&#34;</span>$file_modified<span style="color:#e6db74">\&#34;&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -F <span style="color:#e6db74">&#34;assetData=@\&#34;</span>$INPUT<span style="color:#e6db74">\&#34;&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>id<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>echo <span style="color:#e6db74">&#34;</span>$upload<span style="color:#e6db74">&#34;</span> | jq -r .id<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Uploaded file, asset id is </span>$id<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ---</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Adding file to album </span>$IMMICH_ALBUM<span style="color:#e6db74">...&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>payload<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>jq -n --arg id $id <span style="color:#e6db74">&#39;{ids:[$ARGS.named.id]}&#39;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>album<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>curl -sL --request PUT <span style="color:#e6db74">&#34;</span>$IMMICH_SERVER<span style="color:#e6db74">/api/albums/</span>$IMMICH_ALBUM<span style="color:#e6db74">/assets&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Content-Type: application/json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;Accept: application/json&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -H <span style="color:#e6db74">&#34;X-API-Key: </span>$IMMICH_KEY<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    -d <span style="color:#e6db74">&#34;</span>$payload<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;... done&#34;</span>
</span></span></code></pre></div><h2 id="reacting-to-new-screenshots">Reacting to new screenshots</h2>
<p>I use <a href="https://github.com/watchexec/watchexec">watchexec</a> to listen for changes in my custom screenshot folder
(<a href="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/">see this TIL post on how to set that up</a>)
and calling the upload script with the correct file name. I downloaded a release build of <code>watchexec</code> and threw it into <code>~/.local/bin</code>, then created another
script <code>~/.local/bin/sync-screenshots</code> that takes care of setting all of the correct parameters<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/usr/bin/env bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>WATCHEXEC<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>HOME<span style="color:#e6db74">}</span><span style="color:#e6db74">/.local/bin/watchexec&#34;</span>
</span></span><span style="display:flex;"><span>FOLDER<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>HOME<span style="color:#e6db74">}</span><span style="color:#e6db74">/.steam_screenshots&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">${</span>WATCHEXEC<span style="color:#e6db74">}</span> --exts jpg,png,mp4 --fs-events create --emit-events-to environment -w $FOLDER -o queue -p -v -- <span style="color:#e6db74">&#39;/home/deck/.local/bin/immich-upload.sh &#34;$WATCHEXEC_COMMON_PATH/$WATCHEXEC_CREATED_PATH&#34;&#39;</span>
</span></span></code></pre></div><h2 id="putting-it-all-together">Putting it all together</h2>
<p>Finally, a new systemd unit in <code>~/.config/systemd/user/sync-screenshots.service</code> takes care of starting this bash script and keeping it running:</p>
<pre tabindex="0"><code>[Unit]
Description=Sync Steam Screenshots

[Service]
ExecStart=%h/.local/bin/sync-screenshots
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target
</code></pre><p>I enabled and started that:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>systemctl --user enable sync-screenshots
</span></span><span style="display:flex;"><span>systemctl --user start sync-screenshots
</span></span></code></pre></div><p>Then I took a screenshot and confirmed that the script had run:</p>
<pre tabindex="0"><code>Mar 25 15:17:03 steamdeck sync_screenshots[77135]: [Running: /home/deck/.local/bin/immich-upload.sh &#34;$WATCHEXEC_COMMON_PATH/$WATCHEXEC_CREATED_PATH&#34;]
Mar 25 15:17:03 steamdeck sync_screenshots[77188]: Uploading /home/deck/.steam_screenshots/7_20250325151703_1.png to immich...
Mar 25 15:17:04 steamdeck sync_screenshots[77188]: Uploaded file, asset id is 141dc605-edef-48f1-83b5-00bd9d72b13e
Mar 25 15:17:04 steamdeck sync_screenshots[77188]: Adding file to album 0ce35e68-a564-4e26-921e-c486cd9e4725...
Mar 25 15:17:05 steamdeck sync_screenshots[77188]: ... done
Mar 25 15:17:05 steamdeck sync_screenshots[77135]: [Command was successful]
</code></pre><p>And indeed, upon checking my immich instance, I was also looking at the freshly uploaded screenshot. Mission accomplished!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>It&rsquo;s currently reacting to newly added <code>jpg</code>, <code>png</code> or <code>mp4</code> files. The latter is in preparation of hopefully another toolchain to automatically convert clips from
<a href="https://store.steampowered.com/gamerecording">Steam&rsquo;s game recorder</a> that will automatically push its results into the screenshot folder as well, but that&rsquo;s only an idea for now.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>How to fix GRUB after a SteamOS update</title><link>https://foosel.net/til/how-to-fix-grub-after-steamos-update/</link><pubDate>Sat, 25 Nov 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/how-to-fix-grub-after-steamos-update/</guid><description>&lt;p&gt;My partner just ran into an issue after updating his SteamDeck to the latest SteamOS version (3.4.x to 3.5.7).&lt;/p&gt;
&lt;p&gt;He has a dual boot setup running using &lt;a href="https://github.com/jlobue10/SteamDeck_rEFInd"&gt;rEFInd&lt;/a&gt;, and while that survived the OS update just fine, when he wanted to return to SteamOS after a quick stint in Windows today, he was greeted by a GRUB boot menu.&lt;/p&gt;
&lt;p&gt;Detective foosel to the rescue.&lt;/p&gt;
&lt;p&gt;Attempting to boot the SteamOS entry in grub resulted in an error like this (with another device UUID):&lt;/p&gt;</description><content:encoded><![CDATA[<p>My partner just ran into an issue after updating his SteamDeck to the latest SteamOS version (3.4.x to 3.5.7).</p>
<p>He has a dual boot setup running using <a href="https://github.com/jlobue10/SteamDeck_rEFInd">rEFInd</a>, and while that survived the OS update just fine, when he wanted to return to SteamOS after a quick stint in Windows today, he was greeted by a GRUB boot menu.</p>
<p>Detective foosel to the rescue.</p>
<p>Attempting to boot the SteamOS entry in grub resulted in an error like this (with another device UUID):</p>
<pre tabindex="0"><code>error: no such device: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
error: file `/boot/vmlinuz-linux-neptune` not found.
error: you need to load the kernel first.

Press any key to continue...
</code></pre><p>So it couldn&rsquo;t find it&rsquo;s boot device and due to that also not the kernel stored thereon.</p>
<p>Entering the Deck&rsquo;s boot manager and manually booting <code>\efi\steamos\steamoscl.efi</code> also led to the same situation.</p>
<p>I was able to still boot into SteamOS via the fallback entry however (which also had a different boot device UUID).</p>
<p>And it took me way too long<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> to simply just get the idea to let Linux update its GRUB entries:</p>
<pre tabindex="0"><code>sudo update-grub
</code></pre><p>That fixed it.</p>
<p>No idea if the dual boot setup played a roll in this mess or if it was just some random hiccup, my Deck&rsquo;s update went without a hitch 🤷‍♀️ But if it happens again I now have this entry to check 😁</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I reinstalled rEFInd, rebuilt the EFI entries (<code>sudo efibootmgr -c -d /dev/nvme0n1 -p 1 -L &quot;SteamOS&quot; -l \\efi\\steamos\\steamcl.efi</code>) and the initramfs files (<code>mkinitcpio -P</code>) before getting the idea to maybe start at the bottom instead of the top.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>How to add Battle.net games to the Steamdeck</title><link>https://foosel.net/til/how-to-add-battle-net-games-to-the-steamdeck/</link><pubDate>Sat, 15 Apr 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/how-to-add-battle-net-games-to-the-steamdeck/</guid><description>&lt;p&gt;&lt;em&gt;Update 2023-06-07: It turns out that these days, the by far easiest way to get Battle.net on the SteamDeck is using &lt;a href="https://github.com/moraroy/NonSteamLaunchers-On-Steam-Deck"&gt;NonSteamLaunchers-On-Steam-Deck&lt;/a&gt;, as I recently saw on &lt;a href="https://www.gamingonlinux.com/2023/05/get-battlenet-ea-epic-games-and-more-on-steam-deck-the-easy-way/"&gt;Gaming On Linux&lt;/a&gt;. I haven&amp;rsquo;t gotten a chance to try this myself yet, but it certainly looks very much straight forward, albeit not featuring individual game entries in Steam. For your quick Diablo fix, it should hopefully be just fine though.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Battle.net is currently having a spring sale and I&amp;rsquo;ve been eyeing Diablo II: Resurrected for a while now, so I jumped on the chance (and while at it also got StarCraft Remastered). But given that these days I primarily game on the Steamdeck, I needed to find a way to install Battle.net on my deck and also install individual launchers for the games.&lt;/p&gt;</description><content:encoded><![CDATA[<p><em>Update 2023-06-07: It turns out that these days, the by far easiest way to get Battle.net on the SteamDeck is using <a href="https://github.com/moraroy/NonSteamLaunchers-On-Steam-Deck">NonSteamLaunchers-On-Steam-Deck</a>, as I recently saw on <a href="https://www.gamingonlinux.com/2023/05/get-battlenet-ea-epic-games-and-more-on-steam-deck-the-easy-way/">Gaming On Linux</a>. I haven&rsquo;t gotten a chance to try this myself yet, but it certainly looks very much straight forward, albeit not featuring individual game entries in Steam. For your quick Diablo fix, it should hopefully be just fine though.</em></p>
<p>Battle.net is currently having a spring sale and I&rsquo;ve been eyeing Diablo II: Resurrected for a while now, so I jumped on the chance (and while at it also got StarCraft Remastered). But given that these days I primarily game on the Steamdeck, I needed to find a way to install Battle.net on my deck and also install individual launchers for the games.</p>
<h2 id="battlenet">Battle.net</h2>
<p>I first made the mistake of trying my luck with installing the Battle.net launcher directly via Steam Proton. Trust me: Don&rsquo;t. Lots of work, doesn&rsquo;t end up well. Instead, I went with <a href="https://lutris.net/">Lutris</a>. Lutris has been installed for a while, but if that&rsquo;s not yet on your deck, install that first via the Discover app. Then:</p>
<ol>
<li>Enter desktop mode</li>
<li>Navigate to <a href="https://lutris.net/games/battlenet/">https://lutris.net/games/battlenet/</a> and click on &ldquo;Install&rdquo;. That will fire up an install script in your Lutris setup. Follow the steps shown to you by the app.</li>
<li>Once the installer has run its course, log into Battle.net. You should now be able to download stuff.</li>
<li>Right click on Battle.net in Lutris, select &ldquo;Add steam shortcut&rdquo; (if that&rsquo;s not available, but &ldquo;Delete steam shortcut&rdquo; is - nothing to do, the shortcut has already been added). This will become available after Steam has been restarted, don&rsquo;t worry about it now.</li>
</ol>
<h2 id="diablo-ii-resurrected">Diablo II: Resurrected</h2>
<p>This will create a Lutris app that uses the same Wine prefix as your Battle.net install. This is important! In desktop mode:</p>
<ol>
<li>Navigate to <a href="https://lutris.net/games/diablo-2-ressurected/">https://lutris.net/games/diablo-2-ressurected/</a> (not a typo, there <em>is</em> a typo in that slug indeed), click &ldquo;Install&rdquo;. Follow the steps.</li>
<li>If not yet done, launch Battle.net and install Diablo II: Resurrected.</li>
<li>Launch Diablo once via Battle.net, exit as soon as you can.</li>
<li>In Lutris, right click on the Diablo entry, select &ldquo;Configure&rdquo; and go to &ldquo;Game options&rdquo;</li>
<li>Click &ldquo;Browse&rdquo; next to &ldquo;Executable&rdquo;. Change it to to <code>/home/deck/Games/battlenet/drive_c/Program Files (x86)/Diablo II Resurrected/D2R.exe</code> (so, one folder up, into the Diablo folder and there select <code>D2R.exe</code>)</li>
<li>Under Arguments add <code>-launch</code></li>
<li>Save</li>
</ol>
<p>Make sure the Steam shortcut for the app is added.</p>
<h2 id="starcraft">StarCraft</h2>
<p>Just as with Diablo II, it is important that the StarCraft entry uses the same Wine prefix as Battle.net. Either duplicate the existing &ldquo;Diablo II: Resurrected&rdquo; entry or alternatively follow steps 1 and 2 above. Then do the following with your game entry:</p>
<ol>
<li>Launch Battle.net, install Starcraft Remastered.</li>
<li>Right click on the designated game entry (either your duplicate of Diablo II, or the Diablo II entry you don&rsquo;t intend to use), select &ldquo;Configure&rdquo;</li>
<li>Under &ldquo;Game info&rdquo;, change the name to &ldquo;Starcraft Remastered&rdquo; and the identifier to &ldquo;starcraft-remastered&rdquo;</li>
<li>Under &ldquo;Game options&rdquo;, change the executable to <code>/home/deck/Games/battlenet/drive_c/Program Files (x86)/StarCraft/x86_64/StarCraft.exe</code> and add <code>-launch</code> to the Arguments</li>
<li>Save</li>
</ol>
<p>The art in Lutris should update automatically. Make sure the Steam shortcut for the app is added.</p>
<p>Once all of that is done, head back into game mode. Feel free to change the art for the newly created entries, e.g. through something like the <a href="https://github.com/SteamGridDB/decky-steamgriddb">SteamGridDB</a> plugin for <a href="https://deckbrew.xyz/">Decky</a>. I also set up a dedicated &ldquo;Battle.net&rdquo; collection and added Battle.net itself plus both games to it.</p>
<p><img alt="Screenshot from the Steamdeck, showing a &ldquo;Battle.net&rdquo; collection containing Battle.net, Diablo II: Resurrected and StarCraft Remastered shortcuts" loading="lazy" src="/til/how-to-add-battle-net-games-to-the-steamdeck/steamdeck-battlenet-1.png"></p>
<p>You should now be able to launch your games through their individual Steam shortcuts. Note that the way we have set up things, Battle.net will not be fully available, so if you need that (for multiplayer or for unlocking DLCs) you&rsquo;ll need to launch through the Battle.net shortcut instead. In the case of the Cartoon skin for StarCraft Remastered, launching Starcraft once through Battle.net sufficed however ^^</p>
<p><img alt="Screenshot of the cartoon skin for StarCraft Remastered" loading="lazy" src="/til/how-to-add-battle-net-games-to-the-steamdeck/steamdeck-battlenet-2.png"></p>
]]></content:encoded></item><item><title>(Almost) one year with the Steamdeck</title><link>https://foosel.net/blog/2023-02-26-one-year-with-the-steamdeck/</link><pubDate>Sun, 26 Feb 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/blog/2023-02-26-one-year-with-the-steamdeck/</guid><description>Yes, it was totally worth it!</description><content:encoded><![CDATA[<p>When Valve announced the Steamdeck back in summer of 2021, I was immediately sold. At that point my primary gaming device - despite owning a quite capable PC with enough computing and graphics power to run even the latest AAA games at a decent enough quality - was my Nintendo Switch, simply because I was not particularly happy about spending my after hours in front of the same PC that I already spend my working hours on. Sitting on the couch and playing something in handheld mode while my partner was playing something on his gaming laptop or the PS4 turned out to be an &ldquo;alone time together&rdquo; scenario we both enjoy very much, and was an additional reason I didn&rsquo;t want to spend hours alone in front of my PC. So, when the reservations opened on July 16th 2021 at 19:00 CEST, I was prepared and spent the next 22min frantically trying and finally succeeding to reserve my spot in the EU 256GB queue. And then the waiting began.</p>
<p>As late February of 2022 rolled around, Valve finally started to work through the queue in weekly batches, and I was eyeing my inbox quite nervously in constant fear of missing my order window. I finally got my mail as part of the third batch on March 14th at 17:36 and ordered the deck minutes later. Then the second phase of waiting started, first for the shipment notification which came on March 16th, and then for the actual delivery. Some delays in shipping made my deck just miss a Friday delivery window and instead I got it into my hands only on the coming Monday, which happened to be March 21st - my birthday. And thus the Steamdeck turned into an unintended birthday present to myself 😅</p>
<p>Now almost one year later I can confirm what I hoped when I reserved mine and what I suspected when the first reviews came in: <strong>Yes, this was one of my best acquisitions of 2022!</strong><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>I may not use it daily, there are still days and sometimes weeks during which I don&rsquo;t play due to the one or other reason, but when I play something it&rsquo;s been pretty much exclusively on my deck for the past year. Pretty much anything I have so far thrown at it has worked just fine and I&rsquo;ve spent some wonderful hours on it, playing things like Death Stranding, In Other Waters, Need for Speed: Heat, Gears: Tactics, Return to Monkey Island and much more, and also the one or other multiplayer session of the The Ascent with my partner.</p>
<p><img alt="foosel&rsquo;s Steam Replay 2022. 79 Games Played, top 2% of players. 266 Achievements, 383 Sessions, 63 New Games" loading="lazy" src="/blog/2023-02-26-one-year-with-the-steamdeck/steam_2022.png"></p>
<p>Not only did I game on it however, it also fuelled my tinkering and making hobby. Right at the start of this year on January 1st I swapped its noisy Delta with a much more silent Huaying fan that I bought from iFixit, and also replaced the 256GB SSD with a 1TB one. The <a href="https://www.ifixit.com/Device/Steam_Deck">iFixit guides</a> where spot on and the deck turned out to be even more self repair compatible than the iFixit repairability score of 7/10 suggested. Only a few days later I opened up my deck again on my quest to create <a href="/blog/2023-01-19-custom-steamdeck-buttons/">custom action buttons</a> for my partner&rsquo;s deck<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> for our anniversary, which were a huge success not only with him - I made it on <a href="https://hackaday.com/2023/01/26/casting-custom-resin-buttons-for-the-steam-deck/">Hackaday</a> for the second time in my life <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> 🤭 And now I already have two third party hall effect joysticks lying around here that I plan to swap in ASAP, and of course I still have plans for even more custom buttons.</p>
<p><img alt="Finished custom coloured buttons in a Steamdeck" loading="lazy" src="../2023-01-19-custom-steamdeck-buttons/poster.jpg"></p>
<p>Recently I also set up <a href="https://www.emudeck.com/">Emudeck</a> on it and immediately played through Simon the Sorcerer on ScummVM. Of course there&rsquo;s now also some Zelda ROMs on there that are just waiting for me to give Hyrule another visit. And a gift of <a href="http://cleogame.com/">Cleo</a> on GOG also made me set up <a href="https://heroicgameslauncher.com/">Heroic Launcher</a> and <a href="/til/how-to-add-itchio-games-to-the-steamdeck/">itch.io</a> for more store options. Of course at some point I also ensured I can use the deck as a development system and installed VS Code on it plus a full OctoPrint dev environment. I installed <a href="https://deckbrew.xyz/">Decky</a> and am very much enjoying plugins like <a href="https://github.com/hulkrelax/hltb-for-deck">HLTB</a> and <a href="https://github.com/SteamGridDB/decky-steamgriddb">SteamGridDB</a>. I&rsquo;ve made sure <a href="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/">my screenshots get synced to a special album in Google Photos</a> so sharing stuff is ridiculously easy. And I printed the one or other accessory for myself, my partner and friends.</p>
<p><img alt="Visual Studio Code with OctoPrint&rsquo;s code running on a Steamdeck in desktop mode. In front of the deck there&rsquo;s a foldable Bluetooth keyboard." loading="lazy" src="/blog/2023-02-26-one-year-with-the-steamdeck/octoprint_ide.jpg"></p>
<p>Finally, I should also say that it has changed my perspective on PC gaming. Before I got the deck, there were regular investments in a faster GPU, more RAM, a faster CPU, a better power supply, to keep a capable gaming system on hand and not lock myself out from the wonderful world that is PC games. But now? I rarely power up my PC these days, after also switching to working from my laptop in late 2022, for energy saving reasons. I&rsquo;m still happy to have it available, for streaming, video cutting, Blender and the one or other Tabletop Simulator session, but overall I&rsquo;m going to save a ton of money in the long-term now I think. The 1080Ti I have in there is still good for all the above for a long time to come, and with the deck being able to play what I tend to play so far, and in a way better way for me - handheld on the couch - I see myself rather invest in a Steamdeck 2.0 than regularly throwing money at more and more ridiculous GPUs.</p>
<p>So, all in all, even one year later I&rsquo;m absolutely happy with my deck as you can see. It turned out to be the <em>perfect</em> device for me and has finally made me tackle my gaming backlog<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>. I&rsquo;m a happy gamer 😊</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>The other was my Ebike.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>He ordered his a day after I received mine and got it half a year later in mid September. Shortly after that the queue was done and since then it&rsquo;s been way faster to get your hands on a deck in EU, US or UK.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>The first time was OctoPrint 😊&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Admittedly it has also contributed to its growth at the same time due to me now buying more stuff on sales and even having subscribed to Humble Choice (<a href="https://www.humblebundle.com/membership?refc=WhoXKx">referral link</a>) 😅&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>How to add itch.io games to the Steamdeck</title><link>https://foosel.net/til/how-to-add-itchio-games-to-the-steamdeck/</link><pubDate>Fri, 24 Feb 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/how-to-add-itchio-games-to-the-steamdeck/</guid><description>&lt;p&gt;I&amp;rsquo;m currently setting up some alternative game stores on my Steamdeck, specifically &lt;a href="https://www.emudeck.com/"&gt;Emudeck&lt;/a&gt; for my retro collection, &lt;a href="https://heroicgameslauncher.com/"&gt;Heroic Launcher&lt;/a&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; for GOG and Epic, and also &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I stumbled across &lt;a href="https://www.reddit.com/r/SteamDeck/comments/vwili3/better_way_to_itchio_on_steam_deck/"&gt;this Reddit post&lt;/a&gt; that recommended to use the itch.io Windows launcher instead of the native Linux one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Itch.io has an app, that even has linux version. But it has issues - it can only use one wine version, if you have it installed globally, it can&amp;rsquo;t even handle linux games well. It pretends to install them, and when you launch them it opens a directory with the zip file&amp;hellip; Or it just doesn&amp;rsquo;t work after installation. Then you need to add all the games to steam, setup their images, and other stuff. There&amp;rsquo;s boilr for that, but it doesn&amp;rsquo;t find everything, and most of the indies are not in the database anyway.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;m currently setting up some alternative game stores on my Steamdeck, specifically <a href="https://www.emudeck.com/">Emudeck</a> for my retro collection, <a href="https://heroicgameslauncher.com/">Heroic Launcher</a><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> for GOG and Epic, and also <a href="https://itch.io">itch.io</a>.</p>
<p>I stumbled across <a href="https://www.reddit.com/r/SteamDeck/comments/vwili3/better_way_to_itchio_on_steam_deck/">this Reddit post</a> that recommended to use the itch.io Windows launcher instead of the native Linux one:</p>
<blockquote>
<p>Itch.io has an app, that even has linux version. But it has issues - it can only use one wine version, if you have it installed globally, it can&rsquo;t even handle linux games well. It pretends to install them, and when you launch them it opens a directory with the zip file&hellip; Or it just doesn&rsquo;t work after installation. Then you need to add all the games to steam, setup their images, and other stuff. There&rsquo;s boilr for that, but it doesn&rsquo;t find everything, and most of the indies are not in the database anyway.</p>
</blockquote>
<p>Sounds reasonable to go with the Windows version then, so I followed the post and got everything working. Quick summary in case the link goes stale:</p>
<ul>
<li>In desktop mode, download the Windows installer from <a href="https://itch.io/app">https://itch.io/app</a>, add it as a non steam game, configure stable Proton for it, launch it, complete the installer and log in.</li>
<li>Open Dolphin, navigate to <code>home/deck/.steam/steam/steamapps/compatdata</code></li>
<li>Click on the search icon, check &ldquo;From here&rdquo;, search for <code>itch</code> and enter the first found folder of that name. Look at the address bar, you&rsquo;ll be in a subfolder of something like <code>/home/deck/.steam/steam/steamapps/compatdata/&lt;number&gt;</code> for a random <code>&lt;number&gt;</code>, this parent folder is what to use for <code>&lt;basefolder&gt;</code> in any following steps.</li>
<li>In desktop Steam, open the preferences of your non-steam itch.io installer &ldquo;game&rdquo;. Replace &ldquo;Target&rdquo; with <code>&lt;basefolder&gt;/pfx/drive_c/users/steamuser/Desktop/itch.lnk</code> and &ldquo;Start in&rdquo; with <code>&lt;basefolder&gt;/pfx/drive_c/users/steamuser/AppData/Local/Itch</code>. Rename it to &ldquo;itch.io&rdquo; or whatever else you want it to be called<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</li>
</ul>
<p>I then followed the steps to also allow <a href="https://steamgriddb.github.io/steam-rom-manager/">Steam Rom Manager</a> to detect my itch.io games, and created a custom itch.io parser. Here I had to slightly deviate from the suggested steps. Again, summarised here for reference:</p>
<ul>
<li>Parser type: glob</li>
<li>Title: <code>itch.io</code></li>
<li>Steam category: <code>${itch.io}</code></li>
<li>Steam directory: <code>${steamdirglobal}</code></li>
<li>ROMs directory: <code>&lt;basefolder&gt;/pfx/drive_c/users/steamuser/AppData/Roaming/itch/apps</code></li>
<li>Executable modifier: <code>&quot;${exePath}&quot;</code> (with quotes!)</li>
<li>User&rsquo;s glob: <code>${title}/{*/,}!(Unity*).exe</code> <strong>(this one is different than on the Reddit post, see below for why!)</strong></li>
<li>Leave anything else as is.</li>
</ul>
<p>I changed the glob pattern as the original setting of <code>${title}/{*/*,*}.exe</code> was happily detecting the Unity crash handler executable contained in some games as additional entry, obviously not what I wanted.</p>
<p>After some trial and error I thankfully was able to solve this with the slightly different glob pattern of <code>${title}/{*/,}!(Unity*).exe</code>. It now matches any <code>exe</code> right in the game folder or one folder deep that <em>doesn&rsquo;t</em> start with the string <code>Unity</code>. And if push comes to shove I can add additional forbidden patterns as well.</p>
<p>Even Unity games now only generate one entry, and seem to work fine once I&rsquo;ve figured out the right Proton version 👍</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Basically a one click install from the &ldquo;Discover&rdquo; app in desktop mode.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>My SteamGridDB <a href="https://deckbrew.xyz/">Decky</a> plugin seemed happy with that name as I was able to quickly download matching artwork once back in Game mode.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>How to automatically sync screenshots from the Steamdeck to Google Photos</title><link>https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/</link><pubDate>Sun, 19 Feb 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/</guid><description>&lt;p&gt;As a follow-up to &lt;a href="https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-drive/"&gt;my earlier post about how to sync screenshots to Google Drive&lt;/a&gt; here&amp;rsquo;s how to achieve the same but with a dedicated &amp;ldquo;Steamdeck&amp;rdquo; album on Google Photos instead.&lt;/p&gt;
&lt;p&gt;Once again we are using &lt;code&gt;rclone&lt;/code&gt; for syncing.&lt;/p&gt;
&lt;p&gt;First I created a new target &lt;code&gt;gphoto&lt;/code&gt; by running &lt;code&gt;~/bin/rclone config&lt;/code&gt; again and then following &lt;a href="https://rclone.org/googlephotos/"&gt;these steps&lt;/a&gt;. Quick summary:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;New remote&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gphoto&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Empty application ID and secret&lt;/li&gt;
&lt;li&gt;Full access&lt;/li&gt;
&lt;li&gt;No advanced config&lt;/li&gt;
&lt;li&gt;Use web browser to authenticate&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I then created a new album:&lt;/p&gt;</description><content:encoded><![CDATA[<p>As a follow-up to <a href="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-drive/">my earlier post about how to sync screenshots to Google Drive</a> here&rsquo;s how to achieve the same but with a dedicated &ldquo;Steamdeck&rdquo; album on Google Photos instead.</p>
<p>Once again we are using <code>rclone</code> for syncing.</p>
<p>First I created a new target <code>gphoto</code> by running <code>~/bin/rclone config</code> again and then following <a href="https://rclone.org/googlephotos/">these steps</a>. Quick summary:</p>
<ol>
<li><code>New remote</code></li>
<li><code>gphoto</code></li>
<li>Empty application ID and secret</li>
<li>Full access</li>
<li>No advanced config</li>
<li>Use web browser to authenticate</li>
</ol>
<p>I then created a new album:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>rclone mkdir gphoto:album/Steamdeck
</span></span></code></pre></div><p>and adjusted <code>~/bin/sync_screenshots</code> to use the new remote and remote path:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>REMOTE_NAME<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;gphoto&#39;</span>
</span></span><span style="display:flex;"><span>REMOTE_DIR<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;album/Steamdeck&#39;</span>
</span></span></code></pre></div><p>That was all.</p>
<p>Obviously the same can be done with any of the other sync targets that <code>rclone</code> supports, of which <a href="https://rclone.org/overview/">there are many</a>. For ownCloud or NextCloud it looks like <a href="https://rclone.org/webdav/">WebDAV</a> is the right option to choose.</p>
<p><em>Update 2025-03-25</em>: There&rsquo;s now also a <a href="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-immich/">TIL on how to do the same for Immich</a>.</p>
]]></content:encoded></item><item><title>How to automatically sync screenshots from the Steamdeck to Google Drive</title><link>https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-drive/</link><pubDate>Sat, 11 Feb 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-drive/</guid><description>&lt;p&gt;I wanted to automatically sync the screenshots I take on my Steamdeck to some cloud, without having to manually do it for every single one in the Steamdeck&amp;rsquo;s own uploader.&lt;/p&gt;
&lt;p&gt;I came across &lt;a href="https://gist.github.com/pegasd/048bd5d53558f066765253d55a456306"&gt;this gist by pegasd&lt;/a&gt; that accomplishes this via rclone, a path monitoring systemd service and some reconfiguration in Steam. However, I had to adjust things slightly for everything to really work - I could imagine that some past Steam update changed things slightly vs when the gist was created:&lt;/p&gt;</description><content:encoded><![CDATA[<p>I wanted to automatically sync the screenshots I take on my Steamdeck to some cloud, without having to manually do it for every single one in the Steamdeck&rsquo;s own uploader.</p>
<p>I came across <a href="https://gist.github.com/pegasd/048bd5d53558f066765253d55a456306">this gist by pegasd</a> that accomplishes this via rclone, a path monitoring systemd service and some reconfiguration in Steam. However, I had to adjust things slightly for everything to really work - I could imagine that some past Steam update changed things slightly vs when the gist was created:</p>
<ol>
<li>I had to make sure that I selected the option to make Steam create uncompressed screenshots.</li>
<li>I had to manually start the path watcher.</li>
</ol>
<p>Here&rsquo;s a quick summary of how I managed to make things work on my deck (all credits go to <a href="https://github.com/pegasd">@pegasd</a>, replicating things here mostly so they don&rsquo;t get lost in the future).</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>First of all I switched into Desktop mode.</p>
<p>Since I had not yet done this since upgrading my Deck&rsquo;s SSD, I set a password for my user account by opening a terminal and running <code>passwd</code>. I also made sure to install Firefox from the package manager.</p>
<h2 id="setting-up-the-screenshot-directory">Setting up the screenshot directory</h2>
<p>I opened a terminal and created a dedicated screenshot folder:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir ~/.steam_screenshots
</span></span></code></pre></div><p>Next I had to tell Steam to use this folder. Still in desktop mode I opened Steam settings and on the &ldquo;In-Game&rdquo; tab set the screenshot folder to the one I had just created. I also made sure to check &ldquo;Save uncompressed copy&rdquo;, as <a href="https://steamcommunity.com/discussions/forum/1/4329623982989743690/#c4329623982989971883">otherwise Steam won&rsquo;t use the just configured custom folder</a>.</p>
<h2 id="installing-and-configuring-rclone">Installing and configuring rclone</h2>
<p>Next, still on the deck, I <a href="https://rclone.org/downloads/">downloaded rclone</a> (&ldquo;Intel/AMD - 64 Bit / Linux&rdquo;). I opened the file browser, opened the archive I had just downloaded and extracted the <code>rclone</code> binary into <code>~/bin</code> (if that doesn&rsquo;t exist yet, just create it).</p>
<p>I then went back to the terminal, ran <code>~/bin/rclone config</code> and configured a new remote <code>gdrive</code> following <a href="https://rclone.org/drive/">these steps</a>. Quick summary:</p>
<ol>
<li><code>New remote</code></li>
<li><code>gdrive</code></li>
<li>Empty application ID and secret</li>
<li>Full access to all files</li>
<li>No service account credentials file</li>
<li>Use web browser to authenticate</li>
<li>Not configured as a shared drive</li>
</ol>
<h2 id="automatic-sync">Automatic sync</h2>
<p>I created a file <code>~/bin/sync_screenshots</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/usr/bin/env bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>RCLONE_BIN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>HOME<span style="color:#e6db74">}</span><span style="color:#e6db74">/bin/rclone&#34;</span>
</span></span><span style="display:flex;"><span>REMOTE_NAME<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;gdrive&#39;</span>
</span></span><span style="display:flex;"><span>REMOTE_DIR<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;Privat/Steamdeck/Screenshots&#39;</span>
</span></span><span style="display:flex;"><span>SOURCE_DIR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>HOME<span style="color:#e6db74">}</span><span style="color:#e6db74">/.steam_screenshots&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">${</span>RCLONE_BIN<span style="color:#e6db74">}</span> sync <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>SOURCE_DIR<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>REMOTE_NAME<span style="color:#e6db74">}</span><span style="color:#e6db74">:</span><span style="color:#e6db74">${</span>REMOTE_DIR<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><p>and made it executable with <code>chmod +x ~/bin/sync_screenshots</code>.</p>
<p>Then I created a service file for it, <code>~/.config/systemd/user/sync_screenshots.service</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-plain" data-lang="plain"><span style="display:flex;"><span>[Unit]
</span></span><span style="display:flex;"><span>Description=Sync Steam Screenshots
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[Service]
</span></span><span style="display:flex;"><span>Type=oneshot
</span></span><span style="display:flex;"><span>ExecStart=%h/bin/sync_screenshots
</span></span></code></pre></div><p>and another file setting up a path watcher, <code>~/.config/systemd/user/sync_screenshots.path</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-plain" data-lang="plain"><span style="display:flex;"><span>[Unit]
</span></span><span style="display:flex;"><span>Description=Sync Steam Screenshots
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[Path]
</span></span><span style="display:flex;"><span>PathModified=%h/.steam_screenshots
</span></span><span style="display:flex;"><span>Unit=sync_screenshots.service
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[Install]
</span></span><span style="display:flex;"><span>WantedBy=default.target
</span></span></code></pre></div><p>I enabled the automation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo systemctl daemon-reload
</span></span><span style="display:flex;"><span>systemctl --user enable sync_screenshots.path
</span></span><span style="display:flex;"><span>systemctl --user start sync_screenshots.path
</span></span></code></pre></div><h2 id="a-quick-test">A quick test</h2>
<p>I checked that the path watcher was up and running with <code>systemctl --user status sync_screenshots.path</code>.</p>
<p>Then I created a quick test file in the synced folder</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>touch ~/.steam_screenshots/test
</span></span></code></pre></div><p>and verified it showed up in the target folder on my Google Drive.</p>
<p>Next I deleted the file on the deck and verified it got deleted in Google Drive.</p>
<p>Finally I booted back into Game mode, took a screenshot there as well with <code>Steam</code>+<code>R1</code> and verified this showed up on my Drive.</p>
<p><img alt="A freshly synced screenshot of my Steamdeck&rsquo;s home screen" loading="lazy" src="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-drive/screenshot.png"></p>
<p>Success!</p>
<p><em>Update 2023-02-19</em>: There is now also a <a href="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-google-photos/">TIL on how to do the same for Google Photos</a>.
<em>Update 2025-03-25</em>: And now there&rsquo;s also a <a href="/til/how-to-automatically-sync-screenshots-from-the-steamdeck-to-immich/">TIL on how to do the same for Immich</a>.</p>
]]></content:encoded></item><item><title>Custom SteamDeck Buttons</title><link>https://foosel.net/blog/2023-01-19-custom-steamdeck-buttons/</link><pubDate>Thu, 19 Jan 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/blog/2023-01-19-custom-steamdeck-buttons/</guid><description>Color coded for your convenience</description><content:encoded><![CDATA[<p><em><strong>Update from 2023-02-02</strong> To answer the most common question I&rsquo;ve gotten after publishing this right away: No, I do not plan on selling these. This is something I did for fun and out of love, I&rsquo;m not interested in making money off of it, and I frankly already have my hands full enough as is without adding a custom button business to the mix as well. I&rsquo;ve provided this write-up to give you an idea of how to do it yourself, and I hope you&rsquo;ll enjoy it.</em></p>
<p>My partner and I both got ourselves SteamDecks in 2022. Since then he&rsquo;s repeatedly mentioned that he&rsquo;d love to have
colored buttons on his, matching the XBox controller layout, as many PC games use these colors for their
button hints during quick time events and similar. But sadly, nothing like that is available yet.</p>
<p>With that in mind, and after losing my initial fear about opening up the deck thanks to swapping my fan and upgrading
my SSD on January 1st of this year, an idea for a surprise started to form in my head. I had watched a ton of videos
on silicone molding and resin casting, I have several 3d printers at my disposal, and there was just enough time left
in my vacation and until our anniversary to pull this off. So I went to work. In total secrecy.</p>
<h2 id="research--material-collection">Research &amp; material collection</h2>
<p>The first thing I jumped into was some research in order to be able to make a plan and know what to get.</p>
<p>I ran across <a href="https://bitbuilt.net/forums/index.php?threads/resin-casting-molding-buttons.2316/">this interesting thread</a>
on button casting which gave me a good idea of what I&rsquo;d need in terms of materials. It also taught me that I needed to
figure out what kind of mold I&rsquo;d even need to create for the buttons. Were they flat on the bottom in which case a single part
mold would suffice, or were they curved or otherwise featured, in which case I&rsquo;d need to create a two part mold? Instead of
disassembling my deck right away (too obvious with my partner being around) I decided to instead checkout
<a href="https://www.ifixit.com/Guide/Steam+Deck+Action+Buttons+(ABXY)+Replacement/148950">this excellent disassembly guide on iFixit</a>
which showed me that the buttons are indeed inset on the bottom, and so I&rsquo;d need a two part mold.</p>
<p>That in turn meant I needed to look into mold release for multi part silicone molds in addition to silicone and resin. The
material list in the thread sadly didn&rsquo;t help me - I couldn&rsquo;t get half of this stuff in Germany - but here&rsquo;s what I finally settled on:</p>
<ul>
<li><strong>Reschimica Silicone RPRO 30</strong> (silicone)</li>
<li><strong>Trollfactory Silicone Mold Separation Cream</strong> (two part mold release)</li>
<li><strong>clear two part epoxy resin</strong> (I got this from a friend who happened to have some collecting dust for several months, still sealed)</li>
<li><strong>food vacuumizer pump and container</strong> (to degass silicone and resin, based on an idea from <a href="https://hackaday.com/2019/12/19/degassing-epoxy-resin-on-the-very-cheap/">this hackaday article</a> - a real vaccum chamber and also a pressure pot would have been nice, but I didn&rsquo;t want to break the bank over a bunch of buttons here 😅)</li>
<li><strong>Mica powder</strong> (to color the resin)</li>
<li><strong>white 4mm rub on letters</strong> (to put the lettering on the buttons)</li>
<li><strong>clear UV resin</strong> (to seal the lettering in)</li>
<li><strong>wooden stir sticks</strong></li>
<li><strong>plastic mixing cups</strong></li>
<li><strong>small paper mixing cups</strong></li>
<li><strong>10ml syringes</strong> and <strong>14g blunt needles</strong> (for injecting the resin into the mold)</li>
<li><strong>plastillina clay</strong> (to fix the buttons during the silicone pour)</li>
</ul>
<p>Thanks to owning a resin printer, I already had <strong>a UV flashlight</strong>, <strong>nitrile gloves</strong> and a <strong>respirator</strong> on hand.</p>
<p>And at least one ready to go <strong>FDM 3d printer</strong> for helping me in the mold creation process.</p>
<p><img alt="Most of the materials and tools that I used for this project, as mentioned above." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/materials.jpg"></p>
<h2 id="creating-a-two-part-silicone-mold">Creating a two part silicone mold</h2>
<p>Next step was to create my two part silicone mold and for that I first needed something to fix the buttons to, do the pour for the first
part of the mold, flip that over and create the second part of the mold. I did some more research and came across two
interesting videos, <a href="https://www.youtube.com/watch?v=mjKAkul-VDQ">&ldquo;How To Make Custom PS5 Controller Buttons&rdquo;</a> and
<a href="https://www.youtube.com/watch?v=DfbIYH3xauc">&ldquo;Upgrade Your PS5 Controller with DIY Resin Buttons - Better than the Original!&rdquo;</a>.
In both, EJ uses a 3d printed box with custom bottom to hold the buttons in place and create a keyed two part mold. So, I did
create just that as well. My mold box consists of several parts: two halves forming the box, a bottom for the first part (creating the
keying), a smooth bottom and a top brace for the second part. The bottoms slot into the box halves, the top brace is just friction
fit. Why the top brace? To hold some toothpick halves in place that create channels for resin to go in and air to go out when the
mold is closed.</p>
<p>I designed all this in FreeCAD<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and this is how it looks:</p>
<p><img alt="The mold box configuration for the first pour. Both halves and the keyed bottom." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/mold_case_part1.png"></p>
<p><img alt="The mold box configuration for the second pour. Both halves, the smooth bottom and the cross brace." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/mold_case_part2.png"></p>
<p>You can find the STLs <a href="https://www.printables.com/model/374098-steamdeck-button-mold-case">here</a>. All of the parts were printed
on my heavily modified Prusa MK3 with a 0.6mm nozzle and a 0.3mm layer height in black extrudr PLA NX2 - you might have to adjust
the tolerances on other printers or with other filaments, which is why I also included the FreeCAD file (which could be cleaner,
but it worked for me).</p>
<p>Once I had the mold box ready it was time to disassemble the deck and get the buttons in my hand. So I waited until my partner
was out of the house and then got going.</p>
<p>First, I disassembled everything based on the <a href="https://www.ifixit.com/Guide/Steam+Deck+Action+Buttons+(ABXY)+Replacement/148950">aforementioned iFixit guide</a>. I attached the buttons to their spots on the keyed bottom plate of the mold box with some thin, rolled clay wormy
dealies and then thoroughly cleaned them with some q-tips and isopropyl alcohol. It is important to be <em>very</em> thorough here - any
dirt or even just a fingerprint <em>will</em> show up in the silicone mold and thus in the resin casting as well. I actually found that
the outlines of the letters molded into the original buttons left an impression. The level of details you can get from silicone
molds is astonishing!</p>
<p>Also make sure that you keep the lettering of the buttons oriented the same way, that way you will also
be able to re-use the mold later for buttons with inlayed lettering (which is my plan for version 2.0 of this project).</p>
<p><img alt="The four action buttons mounted to the keyed mold case bottom. My hand hovering over them with a q-tip, a bottle of isopropyl alcohol in reach. In the background the disassembled deck." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/silicone_mold_step1.jpg"></p>
<p>I then slid the bottom plate into the grooves of the mold box halves, sealed the seam with some blue painters tape and just to be
safe also wrapped two rubber bands around it.</p>
<p><img alt="The assembled mold box for the first pour. The buttons are mounted to the bottom. The seems seasled with tape. Two rubber bands go around." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/silicone_mold_step2.jpg"></p>
<p>Now came the time for the first pour. I weighed out 35g each of part A and B into a plastic mixing cup (my silicone gave instructions for mixing 1:1 by weight, stick to your instructions!) and then thoroughly mixed
it with a stir stick. Then I poured that into a <em>second</em> cup, from high above, in a thin stream - this is first to get some of
the bubbles out but more importantly to prevent any unmixed silicone from getting into the mold. This cup I then degassed. For my
first pour I actually used a power sander to vibrate the bubbles out, but for the second pour I went with the above mentioned
food vacuumizer - it&rsquo;s easier, you get way less shaky hands out of it, and the results also look better. So, into the food container,
lid on, pump on. I degassed until bubbles stop coming out. Then I slowly poured the silicone into a corner of the mold
box, once again in a thin stream from up high. Take your time here, the slower, the less risk of errant bubbles making it into
the mold. Then I degassed the mold again for a couple minutes and let it cure based on the instructions.</p>
<p><img alt="The box filled with silicone after the first pour." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/silicone_mold_step3.jpg"></p>
<p>Next, I demolded the first part by removing rubber bands and the tape around the box and then carefully pulling the two halves
apart. I then slowly removed the bottom plate from the silicone part as well, being careful to keep the buttons inside<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.
I then cleaned them off of any leftover plastillina clay and any small bits of silicone.</p>
<p><img alt="The cured first part of the silicone mold, with the buttons still inside. The keying created by the bottom plate is visible." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/silicone_mold_step4.jpg"></p>
<p>After that I placed the first part of the mold on the smooth bottom plate and slid that back into the mold box. I then applied a
generous coating of two part mold release. I used an old drybrush for that and liberately spread it all across the silicone and
box surfaces, making extra sure to get into all the corners and creases. I taped the box seams again and then put the top brace
in place. I broke four toothpicks in half, also broke off most of their tips, and then inserted one into each of the brace holds,
pushing into opposite ends of the buttons underneath. This was to create channels for the resin to flow into and air to push
out of the mold.</p>
<p><img alt="The first part of the silicone mold placed back into the mold box. The cross brace is installed and two toothpick halves lead to each button." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/silicone_mold_step5.jpg"></p>
<p>I once again mixed 70g of silicone from 35g of each part A and B, moved into a second cup, degassed it and slowly poured it into
the mold. Then that was degassed as well and left to cure.</p>
<p><img alt="The mold box, once again filled with silicone, and placed in the vacuum container." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/silicone_mold_step6.jpg"></p>
<p>Another 5h later I carefully demolded my two part mold. I once again removed tape, rubber bands and the top brace, pulling out
the toothpick halves in the process. I then carefully pulled the two halves of the box apart again and equally carefully peeled
the two parts of the mold apart from each other.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> I could now remove the buttons, clean them, place them back into the deck and
reassemble it. Then I cut off some of the silicone bits that had been sucked into the internal hollow structure of the buttons
which I <em>did</em> not want to replicate. I was very diligent here to not cut away too much. And then I was the proud owner of a two
part silicone mold for SteamDeck action buttons.</p>
<p><img alt="The finished two part mold, visibly keyed and interlockable." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/silicone_mold_step7.jpg"></p>
<h2 id="resin-time-resin-time-do-do-do-do-resin-time">Resin time, resin time, do do do do, resin time</h2>
<p><em>Wear gloves and a respirator during this!</em></p>
<p>With the mold now ready for action, it was time to try my hand at resin casting. I first assembled the mold, securing the two
halves with four rubber bands. I also attached the mold to a piece of cardboard in the process on which I noted down the location
of each of the buttons inside the mold. This is really important to keep track of which button goes where. With everything being
mirrored thanks to the buttons basically lying on their faces in the mold you otherwise get terribly puzzled and end up with
buttons of the wrong color. Ask me how I know 😅 If you get confused on which button is which, take a close look at the
spaces they left in the mold. The B button of the deck is slightly curved on its outer side due to following the deck&rsquo;s case
curving, and that has helped me a ton to keep track of it and everything else in relation to it.</p>
<p>Next, I mixed up 40ml of resin, so 20ml of each part A and B (my resin gave instructions for mixing 1:1 by volume, check your
instructions!). I degassed it in the vacuum container and then spread it across
four small paper cups, roughly 10ml each. I then added red, greed, blue and yellow mica powder to each of the cups, mixing that
in thoroughly, before placing the cups into the vacuum container and degassing them again. Next, four syringes with blunt 14g
needles were filled with the four colors of resin and then the buttons were filled with the respective color. After getting
confused with the colors on my first try, I double and triple checked each color before filling it in on the second. I carefully inserted
the needle into the inner channel and then slowly pressed the resin in until it came out of the outer channel. On my first
try I made the mistake to overfill, which caused some unintentional color mixing, so be sure to really stop right when the
resin comes out of the air channel.</p>
<p><img alt="The button mold filled with the colored resin, the four small paper cups holding the unused resin sitting next to it in an aluminium tray." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/resin_cast_step1.jpg"></p>
<p>I then let the buttons cure for 24h before taking a first peek.</p>
<p><img alt="The buttons after 24h of curing." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/resin_cast_step2.jpg"></p>
<p>They looked great, but a quick fingernail test on one of the resin pots showed the stuff was not fully hardened yet. It turned
out to take 72h until I could proceed with the finishing steps.</p>
<h2 id="finishing-the-buttons">Finishing the buttons</h2>
<p>I kept the buttons attached to the mold for the final steps, as that helped a lot with keeping everything aligned and
less fiddly (it was fiddly enough as is). I carefully placed the sheet with rub on lettering I had bought over each button,
making sure to center the corresponding letter. Then I rubbed the letter on using the blunt tip of my letter opener. The stuff
didn&rsquo;t want to stick to the smooth top surface very well, which had the upside of allowing me to redo something if I messed up, but also
the downside of me having to be <em>very</em> careful to not mess things up that were already fine. In the end, it took me some tries
but I prevailed.</p>
<p>Then I got out the UV resin, put on the respirator and gloves, and with an old brush softly brushed on a thin layer of
resin on each button, careful not get any drops on the side or pooling, but sealing in the letter. I then cured that for several minutes
with the UV flashlight.</p>
<p>Once the resin was cured I carefully pulled out the buttons from the mold and then cut off the sprue with a flush cutter.</p>
<p><img alt="The four custom buttons sitting on a post-it note." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/finished_buttons1.jpg"></p>
<p>A quick test fit in my deck showed that I needed some light sanding on one side of X, but that was quickly taken care of and
then I had a working set of custom SteamDeck buttons 👍</p>
<p><img alt="Colorful custom action buttons on the right side of a SteamDeck held up to the camera." loading="lazy" src="/blog/2023-01-19-custom-steamdeck-buttons/finished_buttons2.jpg"></p>
<h2 id="where-do-we-go-from-here">Where do we go from here?</h2>
<p>Considering that until Monday January 9th 2023 I had never before touched silicone or epoxy resin, and that by Monday January 16th 2023 I had four self-cast SteamDeck buttons in my hand that while far from perfect looked <em>great</em>, I&rsquo;m <em>very</em>
happy with the result. And the same goes for my partner, who really had absolutely no idea of this until I presented him the
finished buttons on our anniversary. He was and is in awe 😊</p>
<p>However, single colored buttons with rubbed on letters sealed in with UV resin is not my end goal here. After seeing the amazing results one can
achieve with inlaying in EJ&rsquo;s videos, I&rsquo;m really looking forward to trying that out. So the next step will be to cast some inlayed buttons
with the same mold. And I have already printed out the letters on my resin printer 😁</p>
<p><em><strong>Update from 2024-02-14</strong>: The buttons have now been in <strong>very heavy</strong> use by my partner for over a year, and they still look the same as on day 1! No changes on the letters that I rubbed on and sealed with UV resin, and no changes on the buttons themselves either. 👍</em></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>To be more precise, FreeCAD Link Branch version 2022.09.07&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>If one of the buttons slips out of the mold, you can just press it back in. Just make sure it really slots right back in
where it was, same orientation, full depth and everything. I actually had to do this a bunch of times due to the mold making
stretching over several days due to some issues (see next footnote), and having to reassemble the deck in between to keep
the project a secret from my partner. As a consequence, I can now disassemble and reassemble the deck down to the buttons in
around 20min without the guide 😄&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>I actually had to do the second pour thrice: The first time I didn&rsquo;t create the channels with toothpicks, thinking I could
punch them out afterwards - I couldn&rsquo;t. That led to the creation of the top brace. I then made the mistake to further secure the
toothpicks with superglue, which seems to have interacted with the curing process and caused the top layer of the silicone pour
to stay soft, smeary and sticky. So I did it a third time, exactly as described above, just relying on the friction fit of the
toothpicks, and this time everything cured as expected and I had usable channels 😅&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>