<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[yo1dog blog]]></title><description><![CDATA[Projects and programing shenanigans. Also beer.]]></description><link>http://blog.yo1.dog/</link><generator>Ghost 0.11</generator><lastBuildDate>Sat, 11 Apr 2026 22:55:59 GMT</lastBuildDate><atom:link href="http://blog.yo1.dog/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Fix: Ship of Harkinian does not recognize controller, but Windows does]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<ul>
<li>Download the latest community SDL <a href="https://github.com/mdqinc/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt">gamecontrollersdb</a> and replace <code>gamecontrollersdb.txt</code> at the root of your installation directory.</li>
<li><strong>OR:</strong> If it is still not recognized, use the <a href="https://www.generalarcade.com/gamepadtool/">SDL2 Gamepad Tool</a> to generate a mapping for your controller and copy/paste it into <code>gamecontrollersdb.txt</code>.</li>
</ul>

<hr>

<p>Ship of Harkinian/SoH/OOT</p>]]></description><link>http://blog.yo1.dog/fix-ship-of-harkinian-does-not-recognize-controller-but-windows-does/</link><guid isPermaLink="false">6fd3454e-619c-4e33-a7b4-eb523d73cb77</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Sat, 09 Aug 2025 18:01:29 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<ul>
<li>Download the latest community SDL <a href="https://github.com/mdqinc/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt">gamecontrollersdb</a> and replace <code>gamecontrollersdb.txt</code> at the root of your installation directory.</li>
<li><strong>OR:</strong> If it is still not recognized, use the <a href="https://www.generalarcade.com/gamepadtool/">SDL2 Gamepad Tool</a> to generate a mapping for your controller and copy/paste it into <code>gamecontrollersdb.txt</code>.</li>
</ul>

<hr>

<p>Ship of Harkinian/SoH/OOT PC Port uses <a href="https://github.com/libsdl-org/SDL">SDL</a> for reading controller inputs. It uses the <code>gamecontrollersdb.txt</code> file at installation root to identify controllers by their GUID and define input mappings.</p>

<p>Each release of SoH comes with a recent version of the community sourced <code>gamecontrollerdb.txt</code> which is managed by the <a href="https://github.com/mdqinc/SDL_GameControllerDB">SDL_GameControllerDB</a> repo. However, new controllers may have been added to the DB since the last SoH release.</p>

<p>If your controller was recently released (such as the 8bitdo N64 controller), try downloading the latest <code>gamecontrollerdb.txt</code> from <a href="https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt">here</a> (right-click, save as...) and replacing the one at the root of your SoH installation. </p>

<p>If your controller is still not recognized, it may not be in the DB, but you can add it yourself:</p>

<ol>
<li>Download and run the <a href="https://www.generalarcade.com/gamepadtool/">SDL2 Gamepad Tool</a>.</li>
<li>Select your controller from the dropdown at the top. If you don't see it, make sure your controller is plugged in before you start the tool.</li>
<li>Click "Create A New Mapping" button.</li>
<li>Follow the UI to map each button and joystick. If your controller has more buttons than the UI controller, not all of them will be usable and you must decide which ones you will ignore. Remember that you can always re-map the inputs from within SoH settings.</li>
<li>When you are done, hit the "Copy Mapping String" button.</li>
<li>Open the <code>gamecontrollerdb.txt</code> file at the root of your SoH installation with any text editor and paste onto a new line at the bottom of the file.</li>
</ol>]]></content:encoded></item><item><title><![CDATA[Fix for WSL vsce: Cannot autolaunch D-Bus without X11 $DISPLAY]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<ul>
<li>Set <code>VSCE_STORE=file</code> environment variable.</li>
<li><strong>OR:</strong> Use the <code>VSCE_PAT</code> environment variable to specify your personal access token.</li>
<li><strong>OR:</strong> Use the <code>-p</code> flag to specify your personal access token.</li>
</ul>

<hr>

<p>The <code>vsce</code> CLI for publishing and managing VSCode extensions attempts to use system-native keychains to manage the secure</p>]]></description><link>http://blog.yo1.dog/fix-for-wsl-vsce-cannot-autolaunch-d-bus-without-x11-display-2/</link><guid isPermaLink="false">f6253c36-f99c-468f-bee8-1875f71decab</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Mon, 29 Nov 2021 23:36:08 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<ul>
<li>Set <code>VSCE_STORE=file</code> environment variable.</li>
<li><strong>OR:</strong> Use the <code>VSCE_PAT</code> environment variable to specify your personal access token.</li>
<li><strong>OR:</strong> Use the <code>-p</code> flag to specify your personal access token.</li>
</ul>

<hr>

<p>The <code>vsce</code> CLI for publishing and managing VSCode extensions attempts to use system-native keychains to manage the secure storage of your Azure/Visual Studios Code personal access token. This fails in WSL as it attempts to use the Secret Service API/libsecret which apparently requires X11 or some GUI environment which is not available (unless maybe if you have WSLg installed?).</p>

<p>There are a 2 simple workarounds:</p>

<p>You can instruct <code>vsce</code> to use file-based storage instead of keychains by setting the environment variable <code>VSCE_STORE=file</code> like so:</p>

<pre class="language-bash"><code>VSCE_STORE<span class="token operator">=</span>file vsce login
</code></pre>

<p>Or, you can skip <code>vsce login</code> entirely and instead provide your personal access token using either the <code>VSCE_PAT</code> environment variable or the <code>-p, --pat</code> flag like so:</p>

<pre class="language-bash"><code>VSCE_PAT<span class="token operator">=</span>youraccesstoken vsce publish
or
vsce publish <span class="token operator">-</span>p youraccesstoken
</code></pre>]]></content:encoded></item><item><title><![CDATA[Apple Magic Keyboard Drivers for Windows 10 (Mouse, Trackpad, also?)]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<ol>
<li>Download and extract the Apple Boot Camp drivers I repackaged: <a href="https://s3.amazonaws.com/s3.yo1.dog/BootCamp-061-51481.zip">BootCamp-061-51481.zip</a></li>
<li>Right-click <code>BootCamp/Drivers/Apple/AppleKeyboardMagic2/Keymagic2.inf</code> (or <code>BootCamp/Drivers/Apple/AppleKeyboard/Keymagic64.inf</code> or appropriate driver) and then "Install".</li>
<li>Unplug and re-plugin your keyboard.</li>
<li>If you want to reverse the fn key behavior, change <code>HKEY_</code></li></ol>]]></description><link>http://blog.yo1.dog/apple-magic-keyboard-drivers-for-windows-10-mouse-trackpad-also/</link><guid isPermaLink="false">3be8dd6f-ae96-4fb2-ac7c-d1437605f3d2</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Thu, 29 Oct 2020 03:53:26 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<ol>
<li>Download and extract the Apple Boot Camp drivers I repackaged: <a href="https://s3.amazonaws.com/s3.yo1.dog/BootCamp-061-51481.zip">BootCamp-061-51481.zip</a></li>
<li>Right-click <code>BootCamp/Drivers/Apple/AppleKeyboardMagic2/Keymagic2.inf</code> (or <code>BootCamp/Drivers/Apple/AppleKeyboard/Keymagic64.inf</code> or appropriate driver) and then "Install".</li>
<li>Unplug and re-plugin your keyboard.</li>
<li>If you want to reverse the fn key behavior, change <code>HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\KeyMagic\OSXFnBehavior</code> and <code>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KeyMagic\OSXFnBehavior</code> from <code>01</code> to <code>00</code>. Restart for registry changes to take effect.</li>
</ol>

<p>If those drivers don't work, try getting latest from the source:</p>

<ol>
<li>Download latest exe from <a href="https://github.com/timsutton/brigadier/releases">Brigadier release page</a>.</li>
<li>Find the latest or a current Mac model (ex: <code>MacBookPro16,3</code>).</li>
<li>Run <code>brigadier.exe -m MacBookPro16,3</code> to download Apple Boot Camp drivers.</li>
</ol>

<p>If you can't or don't want to use Brigadier, see the bottom of this post.</p>

<hr>

<p><em>Note: I have not tested this over Bluetooth. I keep my keyboard connected via the supplied lightning to USB cable.</em></p>

<p>I recently acquired an Apple Magic Keyboard and wanted to use it on my PC. It worked when I plugged it in but I could not access any of the media keys/fn keys (ex: volume up and down). This is because Windows was using the default keyboard drivers.</p>

<p>When I first started looking for solutions I found hacky, unsigned drivers and key mappers. These were not ideal.</p>

<p>Apple actually does supply Windows drivers for Apple Keyboards, Apple Magic Keyboards, and apparently other Apple Mouse and Trackpad devices. Apple created these for Boot Camp (a program that allows you to run Windows in a virtual machine in OSX). However, there is not an easy way to access them. Normally, Apple wants you to download and install a large suite of software and drivers meant for Boot Camp which will do all kinds of nasty things to your PC. Thankfully, the keyboard and other drivers can be isolated and installed independently.</p>

<h3 id="downloadbootcampdrivers">Download Boot Camp Drivers</h3>

<p><em>If you want to skip this section, you can download the drivers I extracted from the bellow process and see if they work for you: <a href="https://s3.amazonaws.com/s3.yo1.dog/BootCamp-061-51481.zip">BootCamp-061-51481.zip</a></em></p>

<p>Because we are not going through Boot Camp, the first challenge is getting access to the Boot Camp drivers. The easiest way to do so is to use the <a href="https://github.com/timsutton/brigadier">Brigadier</a> program. This automatically locates the URL for a given Mac model and downloads and extracts the appropriate Boot Camp drivers. If you can't or don't want to use this program, see the bottom of this post.</p>

<p>Download the latest exe from the <a href="https://github.com/timsutton/brigadier/releases">releases page</a> and run it like so:  </p>

<pre><code>brigadier.exe -m MacBookPro16,3
</code></pre>

<p><code>MacBookPro16,3</code> is the model of the latest MacBook Pro (at the time of writing) which I got from <a href="https://support.apple.com/en-us/HT201300">this page</a>. I used this model because I wanted to ensure I got the latest drivers.</p>

<p>This will create a folder next to <code>brigadier.exe</code> named something like <code>BootCamp-061-51481</code>. The numbers in the name will be whatever version of Boot Camp drivers were downloaded.</p>

<h3 id="installdrivers">Install Drivers</h3>

<p>Navigate to <code>BootCamp\Drivers\Apple\AppleKeyboardMagic2</code>  for Apple Magic Keyboard drivers. I have not tested this, but I assume you would use <code>BootCamp\Drivers\Apple\AppleKeyboard</code> for other Apple Keyboards. Or, <code>$WinPEDriver$\AppleMultiTouchTrackPadPro</code> for Apple Magic Trackpad 2, etc. I don't <em>think</em> there is any harm in installing more drivers than you need as only the appropriate ones will be used, but that is also untested.</p>

<p>Right-click <code>Keymagic2.inf</code> (or whichever <code>.inf</code> file exists for your driver) and then "Install" to install the driver.</p>

<p>After installation is complete, unplug and re-plugin your keyboard. If everything worked, you should be able to use the Volume Up/F12 (without holding the fn key) and the Volume will change. To debug, check in device manager; "Apple Keyboard" should be listed under "Human Interface Devices".</p>

<h3 id="changefnkeybehavior">Change fn Key Behavior</h3>

<p>By default, when the fn key is not held, the media keys will be activated. When the fn keys is held the F1-12 keys will be activated.</p>

<p>To reverse the fn key behavior, open RegEdit and navigate to <code>HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\KeyMagic\</code> and update <code>OSXFnBehavior</code> key from <code>01</code> to <code>00</code> (in the binary editor this will update from <code>00000000 01 .</code> to <code>00000000 00 .</code>).</p>

<p>Not sure if this is necessary, but also navigate to <code>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KeyMagic\</code> and make sure the <code>OSXFnBehavior</code> key has the same value.</p>

<p>Restart your PC for the registry changes to take effect.</p>

<h3 id="extradrivers">Extra Drivers</h3>

<p>Poking around in the Boot Camp package, I noticed several other drivers of note. <code>BootCamp\Drivers\Apple\AppleKeyboardInternalUSB</code> may be related to the USB ports on Apple keyboards. There are also some drivers that looked to be related to Apple Mice, Trackpads, Cameras, Displays, etc:</p>

<ul>
<li>BootCamp\Drivers\Apple\AppleCamera</li>
<li>BootCamp\Drivers\Apple\AppleKeyboard</li>
<li>BootCamp\Drivers\Apple\AppleKeyboardInternalUSB</li>
<li>BootCamp\Drivers\Apple\AppleKeyboardMagic2</li>
<li>BootCamp\Drivers\Apple\AppleKeyManager</li>
<li>$WinPEDriver$\AppleMultiTouchTrackPad</li>
<li>$WinPEDriver$\AppleMultiTouchTrackPadPro</li>
<li>$WinPEDriver$\AppleWirelessMouse</li>
<li>$WinPEDriver$\AppleWirelessTrackpad</li>
</ul>

<p>This is not a full list of drivers. Just the ones I found interesting. I have not tested any of these. Again. I don't <em>think</em> there is any harm in installing more drivers than you need as only the appropriate ones will be used, but that is also untested.</p>

<h3 id="brigadieralternative">Brigadier Alternative</h3>

<p>If you can't or don't want to use Brigadier, you can manually find, download, and extract the Boot Camp drivers. Brigadier uses <a href="http://swscan.apple.com/content/catalogs/others/index-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog">this XML file</a> (at the time of writing, subject to change) to locate the correct package. You can do this manually by downloading the XML file, opening it with a text editor, and searching for the <code>BootCampESD.pkg</code> URL with the latest <code>PostDate</code>. Downlad the <code>.pkg</code> file and extract the contents using 7-Zip, WinZip, WinRAR, or any other utility capable of unpacking <code>.pkg</code> and <code>.dmg</code> files:</p>

<ol>
<li>Extract <code>Payload~</code> from <code>BootCampESD.pkg</code></li>
<li>Extract <code>.\Library\Application Support\BootCamp\WindowsSupport.dmg</code> from <code>Payload~</code> (this file is actually an archive).</li>
<li>Extract the contents of <code>WindowsSupport.dmg</code></li>
</ol>

<p>Here are the 7-Zip commands used to accomplish the above:</p>

<pre><code>"C:\Program Files\7-Zip\7z.exe" e -y BootCampESD.pkg
"C:\Program Files\7-Zip\7z.exe" e -y Payload~
"C:\Program Files\7-Zip\7z.exe" x -y WindowsSupport.dmg
</code></pre>]]></content:encoded></item><item><title><![CDATA[AWS CodeStar Notifications TargetType Chatbot Slack Channel]]></title><description><![CDATA[<h2 id="awschatbotslack"><code>AWSChatbotSlack</code></h2>

<p><br>
That's the value to supply for the <code>TargetType</code> parameter when creating an AWS CodeStar notification when you want to target an AWS Chatbot Slack channel.</p>

<p><code>AWSChatbotSlack</code></p>

<p>I don't know why, but this is not listed anywhere in their docs. In fact, a Google search for "AWSChatbotSlack" shows the only</p>]]></description><link>http://blog.yo1.dog/aws-codestar-notifications-targettype-chatbot-slack-channel/</link><guid isPermaLink="false">af08d91b-26c9-490d-9ccf-f7bfdbd56f98</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Tue, 28 Apr 2020 00:10:42 GMT</pubDate><content:encoded><![CDATA[<h2 id="awschatbotslack"><code>AWSChatbotSlack</code></h2>

<p><br>
That's the value to supply for the <code>TargetType</code> parameter when creating an AWS CodeStar notification when you want to target an AWS Chatbot Slack channel.</p>

<p><code>AWSChatbotSlack</code></p>

<p>I don't know why, but this is not listed anywhere in their docs. In fact, a Google search for "AWSChatbotSlack" shows the only place on the entire internet this is mentioned was in an example response on <a href="https://docs.aws.amazon.com/codestar-notifications/latest/userguide/notification-target-view.html">this somewhat-but-not-really related docs page</a>.</p>

<p><strong>Edit:</strong> AWS has updated their <a href="https://docs.aws.amazon.com/codestar-notifications/latest/APIReference/API_Target.html">docs</a> to include this <code>TargetType</code>.</p>]]></content:encoded></item><item><title><![CDATA[Better NVM Lazy Loading]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<pre class="language-bash"><code>export NVM_DIR<span class="token operator">=</span><span class="token string">"<span class="token property">$HOME</span>/.nvm"</span>

<span class="token comment" spellcheck="true"># This lazy loads nvm
</span><span class="token function">nvm<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  unset <span class="token operator">-</span>f nvm
  <span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span> <span class="token operator">--</span>no<span class="token operator">-</span>use <span class="token comment" spellcheck="true"># This loads nvm
</span>  nvm <span class="token property">$@</span>
<span class="token punctuation">}</span>

<span class="token comment" spellcheck="true"># This loads nvm bash_completion
</span><span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/bash_completion"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_</span></span></code></pre>]]></description><link>http://blog.yo1.dog/better-nvm-lazy-loading/</link><guid isPermaLink="false">e4a4ecdb-4f83-4c47-9a3d-55adbdf55ff6</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Fri, 14 Feb 2020 03:33:07 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<pre class="language-bash"><code>export NVM_DIR<span class="token operator">=</span><span class="token string">"<span class="token property">$HOME</span>/.nvm"</span>

<span class="token comment" spellcheck="true"># This lazy loads nvm
</span><span class="token function">nvm<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  unset <span class="token operator">-</span>f nvm
  <span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span> <span class="token operator">--</span>no<span class="token operator">-</span>use <span class="token comment" spellcheck="true"># This loads nvm
</span>  nvm <span class="token property">$@</span>
<span class="token punctuation">}</span>

<span class="token comment" spellcheck="true"># This loads nvm bash_completion
</span><span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/bash_completion"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_DIR</span>/bash_completion"</span>

<span class="token comment" spellcheck="true"># This resolves the default node version
</span>DEFAULT_NODE_VER<span class="token operator">=</span><span class="token string">"$((cat "</span><span class="token property">$NVM_DIR</span><span class="token operator">/</span>alias<span class="token operator">/</span>default<span class="token string">" || cat ~/.nvmrc) 2> /dev/null)"</span>
<span class="token keyword">while</span> <span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/alias/<span class="token property">$DEFAULT_NODE_VER</span>"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">[</span> <span class="token operator">!</span> <span class="token operator">-</span>z <span class="token string">"<span class="token property">$DEFAULT_NODE_VER</span>"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">do</span>
  DEFAULT_NODE_VER<span class="token operator">=</span><span class="token string">"$(cat "</span><span class="token property">$NVM_DIR</span><span class="token operator">/</span>alias<span class="token operator">/</span><span class="token property">$DEFAULT_NODE_VER</span><span class="token string">")"</span>
<span class="token keyword">done</span>

<span class="token comment" spellcheck="true"># This resolves the path to the default node version
</span>DEFAULT_NODE_VER_PATH<span class="token operator">=</span><span class="token string">"$(find <span class="token property">$NVM_DIR</span>/versions/node -maxdepth 1 -name "</span>v$<span class="token punctuation">{</span>DEFAULT_NODE_VER<span class="token comment" spellcheck="true">#v}*" | sort -rV | head -n 1)"
</span>
<span class="token comment" spellcheck="true"># This adds the default node version path to PATH
</span><span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token operator">!</span> <span class="token operator">-</span>z <span class="token string">"<span class="token property">$DEFAULT_NODE_VER_PATH</span>"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span>
  export PATH<span class="token operator">=</span><span class="token string">"<span class="token property">$DEFAULT_NODE_VER_PATH</span>/bin:<span class="token property">$PATH</span>"</span>
<span class="token keyword">fi</span>
</code></pre>

<p>Lazy loaded NVM that behaves as expected without unnecessary complexity or hacks.</p>

<ul>
<li>All binaries - including globally installed npm packages - are available <em>before</em> loading NVM.</li>
<li>NVM is not loaded until the <code>nvm</code> command is used.</li>
<li>Supports the default alias and <code>~/.nvmrc</code>.</li>
<li>Supports alias chains such as <code>default -&gt; lts/erbium -&gt; v12.14.1</code> and partial versions such as <code>v12 -&gt; 12.14.1</code>.</li>
<li>Simple.</li>
</ul>

<p><strong>Caveats:</strong></p>

<ul>
<li>Does not support NVM internal aliases such as <code>stable</code>.</li>
</ul>

<hr>

<p>NVM can add a long delay to your shell startup. Especially in environments like WSL. The solution is to lazy load it. However, the <code>node</code>, <code>npm</code>, <code>npx</code>, and any globally installed npm binaries such as <code>gulp</code>, <code>eslint</code>, etc. are not available until NVM is loaded.</p>

<p>The existing popular solutions fall short for a couple reasons. The top results from an "npm lazy load" Google search suffer some or all of these issues:</p>

<ul>
<li>Whitelists binaries that can be used before loading NVM by creating an alias for each one.
<ul><li>This is cumbersome to maintain as it requires you to create a new alias for every global npm package you install.</li></ul></li>
<li>Requires loading NVM before any of the binaries can be executed.
<ul><li>This just kicks the slow startup problem to the first execution of <code>node</code>, <code>npm</code>, etc. It is also unnecessary as NVM is not required to execute the binaries.</li></ul></li>
<li>Does not support aliases such as <code>lts/erbium</code> as the default.
<ul><li>Requires you to use a specific version as the default.</li></ul></li>
<li>Hardcodes a specific version of node.
<ul><li>Again, cumbersome to maintain as it is disconnected from the default alias and <code>~/.nvmrc</code>. This requires updating whenever you change your default version or behavior will be inconstant with NVM.</li></ul></li>
<li>Uses hacky methods of discovering binaries and other unnecessary complexity.</li>
</ul>

<h2 id="lazyloadnvm">Lazy load NVM</h2>

<p>For reference, here is the boilerplate script NVM installs:  </p>

<pre class="language-bash"><code>export NVM_DIR<span class="token operator">=</span><span class="token string">"<span class="token property">$HOME</span>/.nvm"</span>
<span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span>  <span class="token comment" spellcheck="true"># This loads nvm
</span><span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/bash_completion"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_DIR</span>/bash_completion"</span>  <span class="token comment" spellcheck="true"># This loads nvm bash_completion
</span></code></pre>

<p>Let's lazy load instead:  </p>

<pre class="language-bash"><code>export NVM_DIR<span class="token operator">=</span><span class="token string">"<span class="token property">$HOME</span>/.nvm"</span>

<span class="token comment" spellcheck="true"># This lazy loads nvm
</span><span class="token function">nvm<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  unset <span class="token operator">-</span>f nvm
  <span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_DIR</span>/nvm.sh"</span> <span class="token operator">--</span>no<span class="token operator">-</span>use <span class="token comment" spellcheck="true"># This loads nvm
</span>  nvm <span class="token property">$@</span>
<span class="token punctuation">}</span>

<span class="token comment" spellcheck="true"># This loads nvm bash_completion
</span><span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/bash_completion"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">"<span class="token property">$NVM_DIR</span>/bash_completion"</span>
</code></pre>

<p>As you can see, the lines for setting <code>NVM_DIR</code> and sourcing <code>bash_completion</code> remain unchanged. We move the code for loading NVM into a function and add the <code>--no-use</code> flag. The function unsets itself, loads NVM, and executes <code>nvm</code>. This way NVM is not loaded until the <code>nvm</code> command is actually used.</p>

<ul>
<li>The <code>--no-use</code> flag prevents NVM from automatically executing <code>nvm use</code> after loading which is unnecessary and can be slow.</li>
</ul>

<h2 id="makebinariesaccessible">Make binaries accessible</h2>

<p>All the binaries are already on your drive ready to go. There is no reason you must load NVM before executing them. All you need to do is include them in <code>PATH</code> (which is exactly what NVM does).  </p>

<pre class="language-bash"><code>export PATH<span class="token operator">=</span><span class="token string">"<span class="token property">$NVM_DIR</span>/versions/node/v12.14.1/bin:<span class="token property">$PATH</span>"</span>
</code></pre>

<p>Now we can access all the <code>v12.14.1</code> binaries without having to load NVM. This includes globally installed npm package binaries.</p>

<p>If you don't mind the version being hardcoded, you can stop here.</p>

<h2 id="usethedefaultversion">Use the default version</h2>

<p>We don't want to hardcode a version. Instead, we want to mirror NVM's behavior and use either the default alias or <code>~/.nvmrc</code>:  </p>

<pre class="language-bash"><code>DEFAULT_NODE_VER<span class="token operator">=</span><span class="token string">"$((cat "</span><span class="token property">$NVM_DIR</span><span class="token operator">/</span>alias<span class="token operator">/</span>default<span class="token string">" || cat ~/.nvmrc) 2> /dev/null)"</span>
</code></pre>

<p>First we try using the default alias. If this fails we try using <code>~/.nvmrc</code>. NVM stores aliases as files and we get the version from its contents just like <code>.nvmrc</code> files.</p>

<h2 id="supportaliases">Support aliases</h2>

<p>It is possible to set the default to an alias (which could, in turn, reference another alias). For example <code>default -&gt; myalias -&gt; lts/erbium -&gt; v12.14.1</code>. Let's follow the chain of possible aliases to get the root version:</p>

<pre class="language-bash"><code><span class="token keyword">while</span> <span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">"<span class="token property">$NVM_DIR</span>/alias/<span class="token property">$DEFAULT_NODE_VER</span>"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">[</span> <span class="token operator">!</span> <span class="token operator">-</span>z <span class="token string">"<span class="token property">$DEFAULT_NODE_VER</span>"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">do</span>
  DEFAULT_NODE_VER<span class="token operator">=</span><span class="token string">"$(cat "</span><span class="token property">$NVM_DIR</span><span class="token operator">/</span>alias<span class="token operator">/</span><span class="token property">$DEFAULT_NODE_VER</span><span class="token string">")"</span>
<span class="token keyword">done</span>
</code></pre>

<p>If <code>alias/$DEFAULT_NODE_VER</code> exists, we know we have an alias. Set <code>DEFAULT_NODE_VER</code> to the contents of the alias and repeat. When it does not exist, assume we have reached the root version and stop.</p>

<ul>
<li><code>[ -s ... ]</code> checks if the alias exists.</li>
<li><code>[ ! -z ... ]</code> checks if we hit a dead-end (and prevents an infinite loop).</li>
</ul>

<h2 id="supportpartialversions">Support partial versions</h2>

<p>It is also possible to set a partial version. For example <code>v12 -&gt; v12.14.1</code>. Let's resolve by matching the newest version with the given version as the prefix:</p>

<pre class="language-bash"><code><span class="token comment" spellcheck="true"># This resolves the path to the default node version
</span>DEFAULT_NODE_VER_PATH<span class="token operator">=</span><span class="token string">"$(find <span class="token property">$NVM_DIR</span>/versions/node -maxdepth 1 -name "</span>v$<span class="token punctuation">{</span>DEFAULT_NODE_VER<span class="token comment" spellcheck="true">#v}*" | sort -rV | head -n 1)"
</span></code></pre>

<ul>
<li><code>v${...#v}</code> ensures the version is always prefixed with exactly 1 <code>v</code> as both <code>12.14.1</code> and <code>v12.14.1</code> are possible.</li>
<li><code>sort -rV</code> order matches versions newest to oldest.</li>
<li><code>head -n 1</code> keep the newest matched version.</li>
</ul>

<h2 id="caveats">Caveats</h2>

<p>This is a poor-man's version of NVM's alias resolution and as such does not support NVM internal aliases such as <code>stable</code>. NVM does not store these aliases in files and instead calculates these on-the-fly.</p>

<h2 id="installation">Installation</h2>

<p>Put it all together and you get the script at the top of this page. Replace the default script NVM added to your <code>.bashrc</code>/<code>.zshrc</code>/etc. Be sure to compare the boilerplate lines for setting <code>NVM_DIR</code>, <code>bash_completion</code>, and <code>nvm.sh</code> as these may change in future versions.</p>]]></content:encoded></item><item><title><![CDATA[How to Calculate Steam ID for Non-Steam Games using JavaScript]]></title><description><![CDATA[<hr>

<p><strong>Edit:</strong> Steam has updated the way IDs are calculated. I have updated this article to match.</p>

<h4 id="tldr">tl;dr:</h4>

<pre class="language-javascript"><code><span class="token keyword">const</span> target <span class="token operator">=</span> <span class="token string">'"C:\\Program Files (x86)\\Origin\\Origin.exe"'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> label <span class="token operator">=</span> <span class="token string">'Fubar Game'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> checksum <span class="token operator">=</span> BigInt<span class="token punctuation">.</span><span class="token function">asUintN<span class="token punctuation">(</span></span><span class="token number">32</span><span class="token punctuation">,</span> <span class="token function">BigInt<span class="token punctuation">(</span></span><span class="token function">require<span class="token punctuation">(</span></span><span class="token string">'crc'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">crc32<span class="token punctuation">(</span></span>target <span class="token operator">+</span> label<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> steamId <span class="token operator">=</span> checksum <span class="token operator">|</span> 0x80000000n<span class="token punctuation">;</span>

<span class="token keyword">const</span> top32</code></pre>]]></description><link>http://blog.yo1.dog/calculate-id-for-non-steam-games-js/</link><guid isPermaLink="false">e0483f92-7856-4d45-bf36-4cf4dd7710bf</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Tue, 19 Nov 2019 16:25:34 GMT</pubDate><content:encoded><![CDATA[<hr>

<p><strong>Edit:</strong> Steam has updated the way IDs are calculated. I have updated this article to match.</p>

<h4 id="tldr">tl;dr:</h4>

<pre class="language-javascript"><code><span class="token keyword">const</span> target <span class="token operator">=</span> <span class="token string">'"C:\\Program Files (x86)\\Origin\\Origin.exe"'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> label <span class="token operator">=</span> <span class="token string">'Fubar Game'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> checksum <span class="token operator">=</span> BigInt<span class="token punctuation">.</span><span class="token function">asUintN<span class="token punctuation">(</span></span><span class="token number">32</span><span class="token punctuation">,</span> <span class="token function">BigInt<span class="token punctuation">(</span></span><span class="token function">require<span class="token punctuation">(</span></span><span class="token string">'crc'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">crc32<span class="token punctuation">(</span></span>target <span class="token operator">+</span> label<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> steamId <span class="token operator">=</span> checksum <span class="token operator">|</span> 0x80000000n<span class="token punctuation">;</span>

<span class="token keyword">const</span> top32 <span class="token operator">=</span> steamId<span class="token punctuation">;</span>
<span class="token keyword">const</span> bottom32 <span class="token operator">=</span> 0x02000000n<span class="token punctuation">;</span>
<span class="token keyword">const</span> legacySteamId <span class="token operator">=</span> <span class="token punctuation">(</span>top32 <span class="token operator">&lt;</span><span class="token operator">&lt;</span> 32n<span class="token punctuation">)</span> <span class="token operator">|</span> bottom32<span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>steamId<span class="token punctuation">.</span><span class="token function">toString<span class="token punctuation">(</span></span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>legacySteamId<span class="token punctuation">.</span><span class="token function">toString<span class="token punctuation">(</span></span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// 3934082902
</span><span class="token comment" spellcheck="true">// 16896757403876327424
</span></code></pre>

<p>Note: You can remove the Node.js dependency on the <code>crc</code> package by replacing <code>require('crc').crc32(...)</code> with any CRC32 implementation (<a href="https://stackoverflow.com/a/18639975/2544290">example</a>).</p>

<hr>

<p>A Steam ID is a 32-bit unsigned integer. To derive it, first  take the <a href="https://en.wikipedia.org/wiki/Cyclic_redundancy_check">CRC32</a> checksum of the concatenated target and label UTF-8 encoded strings. Then set the top bit to 1. Meaning you concat the strings, calculate the checksum, and set the top bit.</p>

<p>A legacy Steam ID (still used in some places like Big Picture mode) is a 64-bit unsigned integer. The top 32 bits are the new Steam ID. The bottom 32 bits are the constant <code>0x02000000</code>. Meaning you start with the new Steam ID, shift left 32 bits, and set the constant bits.</p>

<p>We cast everything to BigInt because <a href="https://stackoverflow.com/a/9643650/2544290">JavaScript numbers cannot accurately represent 64-bit integers</a>. We use <code>BigInt.asUintN(32, ...)</code> to ensure the checksum is an unsigned 32-bit integer (some CRC32 implementations return negative numbers).</p>

<p>The values of the target and label strings should exactly match the values in the Steam UI (include double quotes if and only if they appear in Steam).</p>]]></content:encoded></item><item><title><![CDATA[yo1ddns: Free Dynamic DNS (DDNS) on AWS]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p><br>
<a href="https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/quickcreate?templateUrl=https%3A%2F%2Fs3.amazonaws.com%2Fs3.yo1.dog%2Fcloudformation%2Fyo1ddns%2Fstable%2Fyo1ddns.template.json&amp;stackName=yo1ddns&amp;param_apiAuthPassword=CHANGME&amp;param_apiAuthUsername=changeme&amp;param_apiDomainName=ddns.example.com&amp;param_apiDomainNameACMCertARN=&amp;param_apiDomainNameRoute53ZoneId=&amp;param_targetHostnameWhitelist=dynamicip.example.com&amp;param_targetRoute53ZoneId=">1 click to deploy</a> ... That's it!</p>

<hr>

<p>Well maybe not completely free but only a few pennies if you are already using AWS Route 53. Like $0.75/month max.</p>

<p>Supports IPv4 and IPv6. Provides the same interface as DynDNS (dyn.com) so it <em>should</em> work as a drop-in</p>]]></description><link>http://blog.yo1.dog/yo1ddns-free-dynamic-dns-on-aws/</link><guid isPermaLink="false">57f336e0-3cf7-40e8-9bbc-22b09810fc02</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Wed, 06 Nov 2019 23:04:24 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p><br>
<a href="https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/quickcreate?templateUrl=https%3A%2F%2Fs3.amazonaws.com%2Fs3.yo1.dog%2Fcloudformation%2Fyo1ddns%2Fstable%2Fyo1ddns.template.json&amp;stackName=yo1ddns&amp;param_apiAuthPassword=CHANGME&amp;param_apiAuthUsername=changeme&amp;param_apiDomainName=ddns.example.com&amp;param_apiDomainNameACMCertARN=&amp;param_apiDomainNameRoute53ZoneId=&amp;param_targetHostnameWhitelist=dynamicip.example.com&amp;param_targetRoute53ZoneId=">1 click to deploy</a> ... That's it!</p>

<hr>

<p>Well maybe not completely free but only a few pennies if you are already using AWS Route 53. Like $0.75/month max.</p>

<p>Supports IPv4 and IPv6. Provides the same interface as DynDNS (dyn.com) so it <em>should</em> work as a drop-in replacement. You can configure a domain name and it will automatically configure everything needed to make the API accessible.</p>

<p><a href="https://github.com/yo1dog/yo1ddns">yo1ddns</a> is an <a href="https://docs.aws.amazon.com/cdk/latest/guide/home.html">AWS CDK</a> app. CDK apps generate <a href="https://aws.amazon.com/cloudformation/">AWS CloudFormation</a> stack templates. CloudFormation stacks allow you to easily manage a sets of AWS resources. CDK allows you to build your stacks with code rather than configuring in JSON/YAML which is <em>much</em> better. The CDK CLI also allows you to easily deploy and update your stacks.</p>

<p>The stack consists of an API Gateway, 2 Lambdas, and a few roles and such to tie everything together. One of the Lambdas serves as an API authenticator to support HTTP basic auth. The other handles updating Route 53 DNS records with new IPs. The API proxies requests to the Lambda. Pretty simple.</p>

<p>I added a little bit of code that transforms the CDK generated template into a standalone template which is what powers the 1-click deploy link. Basically a template made to be configured and deployed directly from CloudFormation rather than through CDK.</p>

<p>Checkout the <a href="https://github.com/yo1dog/yo1ddns">GitHub page</a> for more information on how to build and deploy the CDK app.</p>]]></content:encoded></item><item><title><![CDATA[How I Beat the SNES Classic Scalpers and their Bots]]></title><description><![CDATA[<p>I was able to snag 4 SNES Classic pre-orders for me and 3 of my friends despite it being sold-out in seconds. The quick sell-out was largely due to auto-buying scripts/bots which can detect when an item becomes available and purchase multiple of them within seconds. Scalpers are paying</p>]]></description><link>http://blog.yo1.dog/how-i-beat-the-snes-classic-scalpers-and-their-bots/</link><guid isPermaLink="false">01c43477-e465-42a8-b4f4-5f64741200a7</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Sun, 27 Aug 2017 16:56:59 GMT</pubDate><content:encoded><![CDATA[<p>I was able to snag 4 SNES Classic pre-orders for me and 3 of my friends despite it being sold-out in seconds. The quick sell-out was largely due to auto-buying scripts/bots which can detect when an item becomes available and purchase multiple of them within seconds. Scalpers are paying $110 for bots like the Tai Ding bot to snag as many as they can to resell at considerable markups.</p>

<p>These scalpers were out in full force last year for the NES Classic and I almost didn't get one. I refused to be beat this year for the SNES Classic.</p>

<p>As a programmer, I was confident I could beat the scalpers at their own game. So, I wrote my own bot. It worked.</p>

<p>Before you get mad at me and call me a cheater, consider this: Scalpers exist and are not going anywhere. <a href="https://venturebeat.com/2016/11/15/nes-classic-editions-limited-supply-is-attracting-scalpers-and-their-bots/">They say so themselves.</a> A world without scalpers and auto-buying bots would be great, but it is not the world we live in. You can stand on the moral ground that using a bot is always wrong, or you can face the objective truth: A world in which only scalpers use bots is a world in which scalpers control a large amount of the stock. This creates a lucrative market for scalpers. In low stock, high demand scenarios (like the SNES Classic), every item bought for personal use is an item that would have been bought by scalpers. The more we can keep out of the hands of scalpers, the better.</p>

<p>I understand that this is not a solution for most people. I understand that most people can't reverse engineer Walmart's API and boil it down to an optimized, 3 HTTP request streamlined checkout process. But that's what it takes. Only a bot can defeat a bot.</p>

<p>I don't believe everyone having a bot is a good or realistic solution. There are solutions the retailers could implement to defeat or at least cripple bots:</p>

<ul>
<li><del>Require a captcha to purchase high-demand items.</del> Captchas are easily circumvented for a few pennies.</li>
<li>Security through obscurity. Trick bots by adding a new obscure and unpredictable requirement for checkout right before the item becomes available for sale. This would break bots and not allow enough time for them to be fixed.</li>
<li>Create better interfaces for one-click purchasing during high-volume traffic.</li>
<li>Do not require users to race to complete the entire (slow and unreliable) checkout process. Once the item is added to the cart, allow customers a few minutes to complete the checkout process before allowing another customer to claim that stock.</li>
<li>Restrict the number of purchases per address/credit card/driver's license/SSN/etc.</li>
<li>...</li>
</ul>

<p>But, unfortunately, these solutions are not currently implemented and they probably never will be. The retailers do not care who buys their products or why. They know all their stock will be sold regardless.</p>

<p>Despite what you think about bots, in the end, the only way to defeat bad guys with bots is good guys with bots or by making bots ineffective. Currently, bots are very effective.</p>

<p>Further, paying $110 for an auto-buying bot is not much different than paying someone $110 to stand in line for you at a physical store. Or buying all of a store's stock when you get to the front of the line. This kind of behavior is inevitable and inescapable.</p>

<p>I am considering releasing my bot open source so anyone could use it for free. Would this level the playing field? Or only exacerbate the problem? I did not create my bot for scalping, but keep in mind that there is no way to limit my bot (or any bot) to be unusable for scalping.</p>

<p>I am also considering releasing it as a paid service. This way I could do much more to prevent its abuse by scalpers.</p>]]></content:encoded></item><item><title><![CDATA[Original Icon for StarCraft 1.18 Patch]]></title><description><![CDATA[<p><img src="http://yo1.dog/blogAssets/starcraftIconRevert.png" alt=""></p>

<hr>

<h4 id="tldr">tl;dr:</h4>

<ol>
<li>Right-click the StarCraft shortcut</li>
<li>Click "Properties"</li>
<li>Click "Change Icon..." button near the bottom</li>
<li>Select the original icon from the list</li>
<li>Click "OK" button</li>
</ol>

<hr>

<p>If you didn't know, Blizzard released the first patch for StarCraft since 1999. The patch includes various fixes and updates to make the game compatible</p>]]></description><link>http://blog.yo1.dog/original-icon-for-new-starcraft-1-18-patch-2/</link><guid isPermaLink="false">e5abc3e8-375e-40f7-b22f-3756088654eb</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Thu, 25 May 2017 07:02:59 GMT</pubDate><content:encoded><![CDATA[<p><img src="http://yo1.dog/blogAssets/starcraftIconRevert.png" alt=""></p>

<hr>

<h4 id="tldr">tl;dr:</h4>

<ol>
<li>Right-click the StarCraft shortcut</li>
<li>Click "Properties"</li>
<li>Click "Change Icon..." button near the bottom</li>
<li>Select the original icon from the list</li>
<li>Click "OK" button</li>
</ol>

<hr>

<p>If you didn't know, Blizzard released the first patch for StarCraft since 1999. The patch includes various fixes and updates to make the game compatible with modern OSes and Battle.net. It also makes the game 100% free (including Brood War expansion) to get people excited for the upcoming remastered version. Get all the specifics and download the installer from <a href="https://starcraft.com">starcraft.com</a>. Run the installer to patch your existing original installation or to do a complete fresh install.</p>

<p>The patch updates the game's EXE icon to a modernized version which I am not a fan of (kills the nostalgia). However, they were nice enough to include the original icon in the EXE as well. Follow the instructions above to get the original icon to display on your shortcuts.</p>

<p>I tried using <a href="http://www.angusj.com/resourcehacker/">Resource Hacker</a> to change the first/default icon stored in <code>StarCraft.exe</code> (Right-click <code>Icon</code> folder, replace icon...) but afterwards attempting to launch the game resulted in an immediate crash. I prefer this method over changing shortcut icons. Anyone got any ideas on how to accomplish this?</p>]]></content:encoded></item><item><title><![CDATA[Updating Enum Values in PostgreSQL - The Safe and Easy Way]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>To update a value in version 10 and up (<em>thanks Vlad for the heads up</em>):  </p>

<pre class="language-sql"><code><span class="token keyword">ALTER</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">RENAME</span> <span class="token keyword">VALUE</span> <span class="token string">'waiting'</span> <span class="token keyword">TO</span> <span class="token string">'blocked'</span><span class="token punctuation">;</span>
</code></pre>

<p>To remove a value in any version or update a value in version 9.6 and bellow:  </p>

<pre class="language-sql"><code><span class="token comment" spellcheck="true"># rename the existing type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TYPE</span> status_</code></pre>]]></description><link>http://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/</link><guid isPermaLink="false">63290754-bd39-4384-9b97-05c42db9b74f</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Wed, 29 Mar 2017 18:48:33 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>To update a value in version 10 and up (<em>thanks Vlad for the heads up</em>):  </p>

<pre class="language-sql"><code><span class="token keyword">ALTER</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">RENAME</span> <span class="token keyword">VALUE</span> <span class="token string">'waiting'</span> <span class="token keyword">TO</span> <span class="token string">'blocked'</span><span class="token punctuation">;</span>
</code></pre>

<p>To remove a value in any version or update a value in version 9.6 and bellow:  </p>

<pre class="language-sql"><code><span class="token comment" spellcheck="true"># rename the existing type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">RENAME</span> <span class="token keyword">TO</span> status_enum_old<span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># create the new type
</span><span class="token keyword">CREATE</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">AS</span> <span class="token keyword">ENUM</span><span class="token punctuation">(</span><span class="token string">'queued'</span><span class="token punctuation">,</span> <span class="token string">'running'</span><span class="token punctuation">,</span> <span class="token string">'done'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># update the columns to use the new type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> job <span class="token keyword">ALTER</span> <span class="token keyword">COLUMN</span> job_status <span class="token keyword">TYPE</span> status_enum <span class="token keyword">USING</span> job_status::<span class="token keyword">text</span>::status_enum<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true"># if you get an error, see bottom of post
</span>
<span class="token comment" spellcheck="true"># remove the old type
</span><span class="token keyword">DROP</span> <span class="token keyword">TYPE</span> status_enum_old<span class="token punctuation">;</span>
</code></pre>

<hr>

<p>PSQL provides an easy way to <em>add</em> new values to an enum: <code>ALTER TYPE name ADD VALUE ...</code>. Version 10 introduced an easy way to <em>update</em> existing values: <code>ALTER TYPE name RENAME VALUE ...</code>. Unfortunately, there is no way to <em>remove</em> values in any version (as of 12) and no way to <em>update</em> values in 9.6 and bellow. The most popular solutions I found for this problem were always one of these two:</p>

<p><strong>"Drop and re-create the type."</strong><br>
This solution alone is no good if the type is already in use as you would have to drop any columns that use the type or temporarily change the column type to <code>TEXT</code>. This has some (slight) disadvantages and there is a sleeker solution.</p>

<p><strong>"Modify the system tables with DELETE FROM pg_enum..."</strong><br>
No! hacking the catalogs is dangerous, unpredictable, and almost always a bad idea.</p>

<p>Instead, lets create a new type with the correct enum values and swap out the old one. This way we don't have to drop and recreate columns nor modify system tables.</p>

<h2 id="examplescenario">Example Scenario</h2>

<pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">AS</span> <span class="token keyword">ENUM</span><span class="token punctuation">(</span><span class="token string">'queued'</span><span class="token punctuation">,</span> <span class="token string">'waiting'</span><span class="token punctuation">,</span> <span class="token string">'running'</span><span class="token punctuation">,</span> <span class="token string">'done'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> job <span class="token punctuation">(</span>
  id         <span class="token keyword">int</span><span class="token punctuation">,</span>
  job_status status_enum
<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> job <span class="token keyword">VALUES</span>
  <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'queued'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'waiting'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token string">'running'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token string">'done'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>

<h2 id="removingavalue">Removing a Value</h2>

<p>Lets say we want to remove the <code>waiting</code> status and set all <code>waiting</code> jobs to <code>running</code>.</p>

<pre class="language-sql"><code><span class="token comment" spellcheck="true"># remove references to the deprecated value
</span><span class="token keyword">UPDATE</span> job <span class="token keyword">SET</span> job_status <span class="token operator">=</span> <span class="token string">'running'</span> <span class="token keyword">WHERE</span> job_status <span class="token operator">=</span> <span class="token string">'waiting'</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># rename the existing type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">RENAME</span> <span class="token keyword">TO</span> status_enum_old<span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># create the new type
</span><span class="token keyword">CREATE</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">AS</span> <span class="token keyword">ENUM</span><span class="token punctuation">(</span><span class="token string">'queued'</span><span class="token punctuation">,</span> <span class="token string">'running'</span><span class="token punctuation">,</span> <span class="token string">'done'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># update the columns to use the new type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> job <span class="token keyword">ALTER</span> <span class="token keyword">COLUMN</span> job_status <span class="token keyword">TYPE</span> status_enum <span class="token keyword">USING</span> job_status::<span class="token keyword">text</span>::status_enum<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true"># if you get an error, see bottom of post
</span>
<span class="token comment" spellcheck="true"># remove the old type
</span><span class="token keyword">DROP</span> <span class="token keyword">TYPE</span> status_enum_old<span class="token punctuation">;</span>
</code></pre>

<h2 id="updatingrenamingavalue">Updating/Renaming a Value</h2>

<p>Lets say we decided <code>blocked</code> was a better description than <code>waiting</code>. In this case we are simply adding a new value (<code>blocked</code>) and removing an existing value (<code>waiting</code>). So, the process is the same as above except we must add our new value to the existing enum first.</p>

<pre class="language-sql"><code><span class="token comment" spellcheck="true"># add the new value to the existing type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">ADD</span> <span class="token keyword">VALUE</span> <span class="token string">'blocked'</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># update references to the deprecated value
</span><span class="token keyword">UPDATE</span> job <span class="token keyword">SET</span> job_status <span class="token operator">=</span> <span class="token string">'blocked'</span> <span class="token keyword">WHERE</span> job_status <span class="token operator">=</span> <span class="token string">'waiting'</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># rename the existing type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">RENAME</span> <span class="token keyword">TO</span> status_enum_old<span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># create the new type
</span><span class="token keyword">CREATE</span> <span class="token keyword">TYPE</span> status_enum <span class="token keyword">AS</span> <span class="token keyword">ENUM</span><span class="token punctuation">(</span><span class="token string">'queued'</span><span class="token punctuation">,</span> <span class="token string">'blocked'</span><span class="token punctuation">,</span> <span class="token string">'running'</span><span class="token punctuation">,</span> <span class="token string">'done'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true"># update the columns to use the new type
</span><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> job <span class="token keyword">ALTER</span> <span class="token keyword">COLUMN</span> job_status <span class="token keyword">TYPE</span> status_enum <span class="token keyword">USING</span> job_status::<span class="token keyword">text</span>::status_enum<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true"># if you get an error, see bottom of post
</span>
<span class="token comment" spellcheck="true"># remove the old type
</span><span class="token keyword">DROP</span> <span class="token keyword">TYPE</span> status_enum_old<span class="token punctuation">;</span>
</code></pre>

<h2 id="errors">Errors</h2>

<ul>
<li><code>invalid input value for enum {enum name}: "{some value}"</code> - One or more rows have a value (<code>"{some value}"</code>) that is not in your new type. You must handle these rows before you can update the column type.</li>
<li><code>default for column "{column_name}" cannot be cast automatically to type {enum_name}</code> - The default value for the column is not in your new type. You must change or remove the default value for the column before you can update the column type. <em>Thanks to Philipp for this addition.</em></li>
</ul>]]></content:encoded></item><item><title><![CDATA[Installing Markdown/Showdown Extensions in Ghost]]></title><description><![CDATA[<p>Ghost uses <a href="https://github.com/showdownjs/showdown">Showdown</a> to convert markdown to HTML (although, currently it uses its own <a href="https://github.com/ErisDS/showdown">fork</a>). Showdown supports <a href="https://github.com/showdownjs/showdown/wiki/extensions">extensions</a> which allow developers to extend its capabilities and add new features.</p>

<p>Installing a Showdown extension requires building Ghost from source. You can find the details on this <a href="https://github.com/TryGhost/Ghost#developer-install">here</a>.</p>

<h2 id="markdowntohtml">Markdown to HTML</h2>

<p>The</p>]]></description><link>http://blog.yo1.dog/installing-showdown-extensions-in-ghost/</link><guid isPermaLink="false">f35cb246-4636-4f68-9abf-8cb815bddeb3</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Fri, 14 Oct 2016 19:11:50 GMT</pubDate><content:encoded><![CDATA[<p>Ghost uses <a href="https://github.com/showdownjs/showdown">Showdown</a> to convert markdown to HTML (although, currently it uses its own <a href="https://github.com/ErisDS/showdown">fork</a>). Showdown supports <a href="https://github.com/showdownjs/showdown/wiki/extensions">extensions</a> which allow developers to extend its capabilities and add new features.</p>

<p>Installing a Showdown extension requires building Ghost from source. You can find the details on this <a href="https://github.com/TryGhost/Ghost#developer-install">here</a>.</p>

<h2 id="markdowntohtml">Markdown to HTML</h2>

<p>The basic flow from Markdown you type to HTML you see in your posts is:</p>

<ol>
<li>Type Markdown</li>
<li><code>{ghost}/core/client/app/helpers/gh-format-markdown.js</code> uses Showdown to convert the markdown to HTML client-side</li>
<li>HTML is shown in the preview pane to the right</li>
<li>Press "Save Draft"/"Update Post" button</li>
<li><code>{ghost}/core/server/models/post.js</code> uses Showdown to convert the markdown to HTML server-side</li>
<li>HTML is saved to the database</li>
<li>When a user views your post, the saved HTML is presented to them</li>
</ol>

<p>As you can see, the Makdown is converted to HTML twice: once client-side for the preview and again server-side to save to the database.</p>

<h2 id="installextension">Install Extension</h2>

<p>The extension's JavaScript is used only by the admin tool, but it used both client-side (for the preview) and server-side (to save to the database). The extension's CSS is used client-side by both the admin tool and your blog.</p>

<h3 id="clientside">Client-Side</h3>

<p>To install client-side, I create Showdown extensions folder like so: <code>{ghost}/core/client/app/showdown-extensions/extension-name/</code>. Put all extension files in this directory.</p>

<p>Now we need to tell the client-side Showdown instance used by the admin tool to generate the preview to use our extension:</p>

<p><code>{ghost}/core/client/app/helpers/gh-format-markdown.js</code></p>

<pre class="language-javascript"><code><span class="token keyword">import</span> extensionName from <span class="token string">'ghost-admin/showdown-extensions/extension-name/extension.js'</span><span class="token punctuation">;</span>

<span class="token keyword">let</span> showdown <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Showdown<span class="token punctuation">.</span>converter</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  extensions<span class="token punctuation">:</span> <span class="token punctuation">[</span>
    <span class="token string">'ghostimagepreview'</span><span class="token punctuation">,</span> <span class="token string">'ghostgfm'</span><span class="token punctuation">,</span> <span class="token string">'footnotes'</span><span class="token punctuation">,</span> <span class="token string">'highlight'</span><span class="token punctuation">,</span>
    extensionName <span class="token comment" spellcheck="true">// add your extension to the list
</span>  <span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>

<p>If your extension requires CSS to display properly, we need to make sure that CSS is available to both the admin tool pages for the preview and your blog pages for the posts.</p>

<p>Include your CSS in the admin tool's main CSS file like so:</p>

<p><code>{ghost}/core/client/app/styles/app.css</code></p>

<pre class="language-css"><code><span class="token comment" spellcheck="true">/* add your css files to the end of the file */</span>
<span class="token atrule">@import "../showdown-extensions/extension-name/extension.css"<span class="token punctuation">;</span></span>
</code></pre>

<p>Add your CSS to your theme. First put your CSS files in your theme's asset folder <code>{ghost}/content/themes/casper/assets/css/extension.css</code>. Then, include the CSS file in your theme's header:</p>

<p><code>{ghost}/content/themes/casper/default.hbs</code></p>

<pre><code>{{! Styles'n'Scripts }}
&lt;head&gt;
  ...
  &lt;link rel="stylesheet" type="text/css" href="{{asset "css/extension.css"}}" /&gt;
  ...
&lt;/head&gt;
</code></pre>

<h3 id="serverside">Server-Side</h3>

<p>Similar to client-side, create a folder to hold your extension like so: <code>{ghost}/core/server/showdown-extensions/extension-name/</code>. Put your extension files in this directory. Note: CSS files are not needed nor used server-side.</p>

<p>Now we need to tell the server-side Showdown instance used to generate the HTML that is saved to the database (and then displayed to the user) to use our extension:</p>

<p><code>{ghost}/core/server/models/post.js</code></p>

<pre class="language-javascript"><code><span class="token keyword">var</span> extensionName <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">'../showdown-extensions/extension-name/extension.js'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> converter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Showdown<span class="token punctuation">.</span>converter</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  extensions<span class="token punctuation">:</span> <span class="token punctuation">[</span>
    <span class="token string">'ghostgfm'</span><span class="token punctuation">,</span> <span class="token string">'footnotes'</span><span class="token punctuation">,</span> <span class="token string">'highlight'</span><span class="token punctuation">,</span>
    extensionName <span class="token comment" spellcheck="true">// add your extension to the list
</span>  <span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
</code></pre>

<h2 id="finalsteps">Final Steps</h2>

<p>Do a re-build with <code>grunt prod</code> after making all of your changes. This will build all the CSS and JavaScript assets sent to the browser. Also make sure to clear your browsers cache or do a hard refresh so you get the latest assets. Note that you will have to edit and save all your existing posts to generate the HTML with the extension applied.</p>]]></content:encoded></item><item><title><![CDATA[Fix for Tomcat 8 Examples WebApp NullPointerException]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>In <code>webapps/examples/META-INF/context.xml</code>, change:</p>

<pre class="language-markup"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Context</span> <span class="token attr-name">allowLinking</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
</code></pre>

<p>to</p>

<pre class="language-markup"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Context</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Resources</span> <span class="token attr-name">allowLinking</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Context</span><span class="token punctuation">></span></span>
</code></pre>

<hr>

<p>I had just finished a fresh install of Tomcat 8 (<code>yum install tomcat8</code>) on my EC2 instance. I looked at my <code>catalina.out</code> log and saw this:</p>

<pre><code>14-Sep-2016</code></pre>]]></description><link>http://blog.yo1.dog/fix-for-tomcat-8-examples-webapp-nullpointerexception/</link><guid isPermaLink="false">816d576d-a1b7-40c9-88e5-202b669fbeda</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Thu, 15 Sep 2016 00:56:26 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>In <code>webapps/examples/META-INF/context.xml</code>, change:</p>

<pre class="language-markup"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Context</span> <span class="token attr-name">allowLinking</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
</code></pre>

<p>to</p>

<pre class="language-markup"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Context</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Resources</span> <span class="token attr-name">allowLinking</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Context</span><span class="token punctuation">></span></span>
</code></pre>

<hr>

<p>I had just finished a fresh install of Tomcat 8 (<code>yum install tomcat8</code>) on my EC2 instance. I looked at my <code>catalina.out</code> log and saw this:</p>

<pre><code>14-Sep-2016 18:48:54.625 WARNING [localhost-startStop-1] org.apache.catalina.startup.SetContextPropertiesRule.begin [SetContextPropertiesRule]{Context} Setting property 'allowLinking' to 'true' did not find a matching property.

14-Sep-2016 18:48:54.641 SEVERE [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
 org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/examples]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:153)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
        ...
Caused by: java.lang.NullPointerException
        at org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:321)
        at org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:182)
        ...

14-Sep-2016 18:48:54.642 SEVERE [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Error deploying web application directory /var/lib/tomcat8/webapps/examples
 java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/examples]]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:729)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
        ...
</code></pre>

<p>The Examples WebApp from Tomcat was failing to deploy. I hadn't touched any of the config files.</p>

<p>It all starts with that first warning message: <code>Setting property 'allowLinking' to 'true' did not find a matching property.</code>. I did some digging and found that according to this <a href="http://tomcat.apache.org/migration-8.html#Web_application_resources">migration guide</a>, between Tomcat versions 7 and 8 some properties that used to be defined on the Context level now must defined on the Resources level. This includes <code>allowLinking</code>. Sure enough it we look at <code>webapps/examples/META-INF/context.xml</code> we see:</p>

<pre class="language-markup"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Context</span> <span class="token attr-name">allowLinking</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
</code></pre>

<p>I guess Tomcat forgot to update their Examples WebApp for Tomcat 8. Easy enough to fix. Simply replace with:</p>

<pre class="language-markup"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Context</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Resources</span> <span class="token attr-name">allowLinking</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Context</span><span class="token punctuation">></span></span>
</code></pre>

<p>Restart Tomcat and check your logs. Everything should be working now.</p>

<p>How does this fix the NullPointerException? Well, I'm not sure exactly. If you look at the source around that line it is trying to load jars. I was pretty sure the two were connected when I read a <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=56923#c2">comment on a bug</a> about the same issue. When he mentioned the problem had something to do with loading jars and symlinks, I remembered that warning that was printed right before the stack trace.</p>]]></content:encoded></item><item><title><![CDATA[Fix for Linksys EA3500 with OpenWRT  2.4GHz Wifi not working]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>In <code>/etc/config/wireless</code>, under the <code>config wifi-device 'radio0'</code> section, change the <code>option hw_mode '11a'</code> line to <code>option hw_mode '11g'</code> and restart. See the bottom of this post for an example.</p>

<hr>

<p><a href="https://forum.openwrt.org/viewtopic.php?pid=327586">Here</a> is my thread on the OpenWRT forums.</p>

<p>I recently installed <a href="https://openwrt.org/">OpenWRT</a> firmware on my</p>]]></description><link>http://blog.yo1.dog/fix-for-linksys-ea3500-with-openwrt-2-4ghz-wifi-not-working/</link><guid isPermaLink="false">6cab6494-408a-4e27-bb26-b2e7ac63ab23</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Wed, 08 Jun 2016 00:15:51 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>In <code>/etc/config/wireless</code>, under the <code>config wifi-device 'radio0'</code> section, change the <code>option hw_mode '11a'</code> line to <code>option hw_mode '11g'</code> and restart. See the bottom of this post for an example.</p>

<hr>

<p><a href="https://forum.openwrt.org/viewtopic.php?pid=327586">Here</a> is my thread on the OpenWRT forums.</p>

<p>I recently installed <a href="https://openwrt.org/">OpenWRT</a> firmware on my Linksys EA3500 router so I could send WOL (<a href="https://en.wikipedia.org/wiki/Wake-on-LAN">Wake-on-LAN</a>) packets to my PC to turn it on from outside of my local network. Everything worked great except for the 2.4GHz WiFi (radio0).</p>

<p>I looked through the system logs and found this:</p>

<pre><code># logread | grep radio0
...
radio0 (2030): Hardware does not support configured mode
radio0 (2030): wlan0: IEEE 802.11 Hardware does not support configured mode (2) (hw_mode in hostapd.conf)
radio0 (2030): Could not select hw_mode and channel. (-2)
...
</code></pre>

<p>The referenced <code>hostapd.conf</code> is actually <code>/var/run/hostapd-phy0.conf</code> which is automatically generated from <code>/etc/config/wireless</code>. If we look in <code>/etc/config/wireless</code> we see this configuration for radio0:</p>

<pre><code># cat /etc/config/wireless

config wifi-device 'radio0'
        option type 'mac80211'
        option path 'mbus/mbus:pcie-controller/pci0000:00/0000:00:01.0/0000:01:00.0'
        option hwmode '11a'
        option channel 'auto'

...
</code></pre>

<p>"IEEE 802.11 Hardware does not support configured mode (2) (hw_mode" </p>

<p>This error tells us that the WiFi device's wireless protocol (<code>hw_mode</code>/<code>hwmode</code>) has been improperly configured. As you can see from the configuration above, by default radio0 is incorrectly configured as a 5GHz radio with the 802.11a/n protocol (<code>11a</code>). To fix this we need to change the value to <code>11g</code> to correctly configure the radio to use the 802.11b/g/n 2.4GHz protocol.</p>

<p>Specifically, we need to change the <code>option hw_mode '11a'</code> line to <code>option hw_mode '11g'</code> in <code>/etc/config/wireless</code> like so:</p>

<pre><code>config wifi-device 'radio0'
        option type 'mac80211'
        option path 'mbus/mbus:pcie-controller/pci0000:00/0000:00:01.0/0000:01:00.0'
        option hwmode '11g'
        option channel 'auto'
</code></pre>

<p>Restart the router to cause <code>/var/run/hostapd-phy0.conf</code> to be regenerated from your new <code>/etc/config/wireless</code>.</p>]]></content:encoded></item><item><title><![CDATA[Fix for FFmpeg "protocol not on whitelist" Error for HTTP(S) URLs]]></title><description><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>Use <code>-safe 0</code> and <code>-protocol_whitelist file,http,https,tcp,tls</code> arguments before the input arguments. Full example at very bottom.</p>

<hr>

<p>I was trying to use FFmpeg's concat demuxer like so:</p>

<pre><code># inputs.txt
file 'http://www.example1.com/video1.mp4'
file 'https://www.example2.com/video2.mp4'
</code></pre>

<pre class="language-bash"><code>ffmpeg</code></pre>]]></description><link>http://blog.yo1.dog/fix-for-ffmpeg-protocol-not-on-whitelist-error-for-urls/</link><guid isPermaLink="false">d12e4066-c1cc-461c-9cb8-5454d9efe587</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Thu, 26 May 2016 00:22:45 GMT</pubDate><content:encoded><![CDATA[<hr>

<h4 id="tldr">tl;dr:</h4>

<p>Use <code>-safe 0</code> and <code>-protocol_whitelist file,http,https,tcp,tls</code> arguments before the input arguments. Full example at very bottom.</p>

<hr>

<p>I was trying to use FFmpeg's concat demuxer like so:</p>

<pre><code># inputs.txt
file 'http://www.example1.com/video1.mp4'
file 'https://www.example2.com/video2.mp4'
</code></pre>

<pre class="language-bash"><code>ffmpeg <span class="token operator">-</span>f <span class="token string">"concat"</span> <span class="token operator">-</span>i <span class="token string">"./inputs.txt"</span> <span class="token operator">-</span>codec <span class="token string">"copy"</span> <span class="token string">"./concated.mp4"</span> 
</code></pre>

<p>First I got the error:</p>

<pre><code>[concat @ 0x00] Unsafe file name 'http://www.example1.com/video1.mp4'
./inputs.txt: Operation not permitted
</code></pre>

<p>This was solved by adding the <code>-safe 0</code> argument. Then I got the error:</p>

<pre><code>[http @ 0x00] Protocol not on whitelist 'file,crypto'!
[concat @ 0x00] Impossible to open 'http://www.example1.com/video1.mp4'
./inputs.txt: Invalid argument
</code></pre>

<p>I thought I would be able to solve this by simple adding <code>-protocol_whitelist file,http,https</code> but then the error became:</p>

<pre><code>[tcp @ 0x00] Protocol not on whitelist 'file,http,https'!
[concat @ 0x00] Impossible to open 'http://www.example1.com/video1.mp4'
./inputs.txt: Invalid argument
</code></pre>

<p>I did not understand why my HTTP protocol input was still being rejected. <code>http</code> was clearly in the protocol whitelist. Then I noticed the small diference between the previous two errors. Look at the very first word in those errors. <code>http</code> vs <code>tcp</code>. I realized that the first word in brackets before the error was the protocol that was being rejected.</p>

<p>The solution is to also add <code>tcp</code> to the protocol whitelist as well (also <code>tls</code> if you want to support HTTPS). Here was my final command:</p>

<pre class="language-bash"><code>ffmpeg <span class="token operator">-</span>f <span class="token string">"concat"</span> <span class="token operator">-</span>safe <span class="token string">"0"</span> <span class="token operator">-</span>protocol_whitelist <span class="token string">"file,http,https,tcp,tls"</span> <span class="token operator">-</span>i <span class="token string">"./inputs.txt"</span> <span class="token operator">-</span>codec <span class="token string">"copy"</span> <span class="token string">"./concated.mp4"</span> 
</code></pre>]]></content:encoded></item><item><title><![CDATA[Running LEGO Rock Raiders on XP without manually disabling DirectDraw]]></title><description><![CDATA[<p>The only way I could find to be able to run LEGO Rock Raiders on XP was to open the DirectX Diagnostic Tool (<code>DXDiag</code>) and click the disable button next to "DirectDraw" before starting the game. Then I would have to re-enable it afterwards. This is a pain to do</p>]]></description><link>http://blog.yo1.dog/running-lego-rock-raiders-on-xp-without-manually-disabling-directdraw/</link><guid isPermaLink="false">fdc218bf-5224-472f-92b8-fa7c4b9d8bef</guid><dc:creator><![CDATA[Mike Moore]]></dc:creator><pubDate>Sun, 10 Apr 2016 20:56:25 GMT</pubDate><content:encoded><![CDATA[<p>The only way I could find to be able to run LEGO Rock Raiders on XP was to open the DirectX Diagnostic Tool (<code>DXDiag</code>) and click the disable button next to "DirectDraw" before starting the game. Then I would have to re-enable it afterwards. This is a pain to do manually. This script will turn off DirectDraw pragmatically, start the game, and turn it off afterwards - all automatically.</p>

<pre><code>::Turn DirectDraw OFF
Reg Add HKLM\SOFTWARE\Microsoft\DirectDraw /V EmulationOnly /T REG_DWORD /D 1 /F  
Reg Add HKLM\SOFTWARE\Microsoft\Direct3D\Drivers /V SoftwareOnly /T REG_DWORD /D 1 /F

:: Start LEGO Rock Raiders
LegoRR.exe

::Turn DirectDraw ON
Reg Add HKLM\SOFTWARE\Microsoft\DirectDraw /V EmulationOnly /T REG_DWORD /D 0 /F  
Reg Add HKLM\SOFTWARE\Microsoft\Direct3D\Drivers /V SoftwareOnly /T REG_DWORD /D 0 /F  
</code></pre>

<p>Copy and paste this script into notepad and save it as <code>startRockRaiders.cmd</code> in the Rock Raiders installation directory (same folder as <code>LegoRR.exe</code> - default is <code>C:\Program Files\Lego Media\Games\Rock Raiders</code>). Now right-click <code>startRockRaiders.cmd</code> and select "Create Shortcut". Replace any existing Rock Raider shortcuts with this one.</p>

<p>You can make the new shortcut look like the original:</p>

<ol>
<li>Rename it to "Rock Raiders".  </li>
<li>Right-click it and select "Properties".  </li>
<li>Click the "Change Icon..." button.  </li>
<li>Click "OK" if a pop-up comes up complaining about missing icons.  </li>
<li>Click "Browse...", navigate to the Rock Raiders installation directory, select <code>LegoRR.exe</code>, and click "Open".  </li>
<li>You should see the Rock Raiders Icon in the window. Click "OK", then "OK" again.</li>
</ol>

<p>Now you have a shortcut that looks exactly like the old one, but allows you play Rock Raiders without having to manually disable and re-enable DirectDraw every time you want to play.</p>

<p><strong>Note:</strong> This is not a perfect solution. The script waits for the game to exit before it re-enables DirectDraw. If you power off the machine while the game is running DirectDraw will remain disabled and you will have to manually re-enable it. If you notice some graphical issues or slowness after playing double check that DirectDraw is enabled by clicking Start, then click "Run...", type in "DXDiag" and click "OK", click the "Display" tab, and then look below to see the DirectDraw status. Click the button next to it to enable or disable it manually.</p>]]></content:encoded></item></channel></rss>