<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Play on Raúl Negrón-Otero&#39;s Blog</title>
		<link>https://raulnegron.me/play/</link>
		<description>Recent content in Play on Raúl Negrón-Otero&#39;s Blog</description>
		<generator>Hugo</generator>
		<language>en-US</language>
			<lastBuildDate>Mon, 25 Aug 2025 00:00:00 +0000</lastBuildDate>
			<atom:link href="https://raulnegron.me/play/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Patching the Wii News Channel to serve local news in 2025</title>
				<link>https://raulnegron.me/2025/wii-news-pr/</link>
				<pubDate>Mon, 25 Aug 2025 00:00:00 +0000</pubDate>
				<guid>https://raulnegron.me/2025/wii-news-pr/</guid>
				<description>&lt;style&gt;&#xA;img.with-border {&#xA; box-shadow: 0 3px 10px rgba(0,0,0,0.16),&#xA;              0 3px 10px rgba(0,0,0,0.23);&#xA;  border-radius: 4px;&#xA;}&#xA;&lt;/style&gt;&#xA;&lt;p&gt;🎧 &lt;a href=&#34;https://share.m.nintendo.com/en-US/US/tracks/d0ef0907-3709-4850-af8a-b1cf5c63cc6e&#34;&gt;Now Playing: Menu (News Channel) via Nintendo Music App&lt;/a&gt;&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/wii-news-pr.png&#34; alt=&#34;wii system plus PR flag and rolled up newspaper emoji&#34;&gt;&#xA;&lt;p&gt;In keeping with my passion (?) for &lt;a href=&#34;https://github.com/rnegron/noticias-pr-cli&#34;&gt;displaying local news articles in unexpected places&lt;/a&gt;, I figured it would be a fun project to try and see what it would take to display current local news on the Nintendo Wii console&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Wii_system_software#News_Channel&#34;&gt;News Channel&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s a sneak peek at the result:&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/wiinewspr-article.png&#34; alt=&#34;Wii News Channel showing a contemporary news article from El Nuevo Día&#34;&gt;&#xA;&lt;p&gt;In this post, I&amp;rsquo;d like to share my research and process for getting this all to work.&lt;/p&gt;&#xA; &lt;details&gt;&#xA;  &lt;summary&gt;&lt;strong&gt;tl;dr - click to expand (spoilers)&lt;/strong&gt;&lt;/summary&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Patched the News Channel&amp;rsquo;s hardcoded Nintendo URL to point to an S3 storage bucket using Go and &lt;code&gt;wadlib&lt;/code&gt; to extract the necessary binary file and edit it in-memory&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Modified WiiLink&amp;rsquo;s open-source news file generator to add &amp;ldquo;El Nuevo Día&amp;rdquo; as a news source&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Set up AWS Lambda + EventBridge to regenerate the necessary news binary files hourly&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Source code: &lt;a href=&#34;https://github.com/rnegron/WiiNewsPR&#34;&gt;WiiNewsPR&lt;/a&gt; and&#xA;&lt;a href=&#34;https://github.com/rnegron/WiiNewsPR-Patcher&#34;&gt;WiiNewsPR-Patcher&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;  &lt;/details&gt;&#xA;&lt;!-- We&#39;ll get a chance to see console-specific file storage formats, proxy the Wii&#39;s HTTP requests, search for strings in binary files  --&gt;&#xA;&lt;h2 id=&#34;the-wiis-news-channel&#34;&gt;The Wii&amp;rsquo;s News Channel&lt;/h2&gt;&#xA;&lt;p&gt;The News Channel debuted in North America on January 26, 2007, a little over two months after the Wii&amp;rsquo;s launch. Since that date, it mostly came pre-installed with Wii consoles and was a novel way to read news from all over the world. Together with other &amp;ldquo;utility&amp;rdquo; channels like the Forecast Channel, it tried to position the Wii as more than just a gaming console.&lt;/p&gt;&#xA;&lt;p&gt;Check out a video recording of the service from right before it was discontinued on June 27th, 2013:&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;&#x9;&#x9;&#x9;&lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;lazy&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/vP70ioijK6U?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=15&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;&#x9;&#x9;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;how-the-news-channel-fetches-content&#34;&gt;How the News Channel fetches content&lt;/h3&gt;&#xA;&lt;p&gt;Before we can consider displaying custom news on it, we have to figure out how the News Channel actually fetches content. We know that it must have fetched news somehow since it displays a &amp;ldquo;Downloading&amp;hellip;&amp;rdquo; splash screen on startup.&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/downloading.png&#34; alt=&#34;wii news channel downloading splash screen&#34;&gt;&#xA;&lt;p&gt;Luckily for us, the Wii natively supports proxying via its internet connection configuration settings! Meaning we can set up something like &lt;a href=&#34;https://www.mitmproxy.org/&#34;&gt;mitmproxy&lt;/a&gt; on a local machine and observe its HTTP behavior.&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/proxy-settings.png&#34; alt=&#34;wii system internet connection menu showing available proxy settings&#34;&gt;&#xA;&lt;p&gt;We can start &lt;code&gt;mitmproxy&lt;/code&gt;&amp;rsquo;s web interface for a more screenshot-friendly UI:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mitmweb --listen-port &lt;span class=&#34;m&#34;&gt;8080&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we run a man-in-the-middle proxy for the News Channel on an unmodified Wii, we will observe that, on channel startup, it attempts to obtain a &lt;code&gt;news.bin.00&lt;/code&gt; file from &lt;code&gt;http://news.wapp.wii.com/v2/1/049/news.bin.00&lt;/code&gt; via a plain HTTP request.&lt;/p&gt;&#xA;&lt;img class=&#34;with-border&#34; src=&#34;https://raulnegron.me/img/wiinews-pr/original-requests.png&#34; alt=&#34;mitmproxy web showing two HTTP requests from the Wii to http://news.wapp.wii.com/v2/1/049/news.bin.00&#34;&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;URL path explainer (we&amp;rsquo;ll see later how I found this out):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;1&lt;/code&gt; corresponds to &amp;ldquo;English&amp;rdquo; as the configured console language. See &lt;a href=&#34;https://github.com/devkitPro/libogc/blob/9d99fec85cbc27b6ab4f3d785764de611112dbaf/gc/ogc/conf.h#L108&#34;&gt;conf.h&lt;/a&gt; in &lt;code&gt;devkitPro&lt;/code&gt; (the Wii homebrew community&amp;rsquo;s de-facto development toolchain) for the possible values.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;049&lt;/code&gt; is the Wii&amp;rsquo;s country code for &amp;ldquo;United States&amp;rdquo;. Check out the full list of Wii country codes on &lt;a href=&#34;https://wiibrew.org/wiki/Country_Codes&#34;&gt;wiibrew.org&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Once it fails to fetch this file, the News Channel displays an error. What might these binary files be? In any case, seeing the Wii perform an HTTP request to fetch news data is a good sign for us. It means we might be able to serve our own data.&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/wiiconnect24-error.png&#34; alt=&#34;wii news channel error screen&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;By the way, if you run an internet connection test after configuring the proxy settings correctly, you&amp;rsquo;ll spot the Wii performing an HTTP request to &lt;a href=&#34;http://conntest.nintendowifi.net&#34;&gt;http://conntest.nintendowifi.net&lt;/a&gt;. Turns out, this page is actually still online (see for yourself!)&lt;/p&gt;&#xA;&lt;img class=&#34;with-border&#34; src=&#34;https://raulnegron.me/img/wiinews-pr/conn-check.png&#34; alt=&#34;mitmproxy web showing an HTTP requests from the Wii to http://conntest.nintendowifi.net&#34;&gt;&#xA;&lt;p&gt;The Wii&amp;rsquo;s internet connection test still passes to this day without any modification required. Thanks, Nintendo!&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;enter-wiilink-the-homebrew-community-keeping-wii-online-services-alive&#34;&gt;Enter WiiLink: the homebrew community keeping Wii online services alive&lt;/h2&gt;&#xA;&lt;p&gt;Up to this point, this is how we would expect the Wii would behave if you were running a stock console. More than 12 years ago, &lt;a href=&#34;https://www.nintendo.com/en-gb/Support/Wii/Wii-Channels/Wii-Network-Services-Partial-Discontinuation/Wii-Network-Services-Partial-Discontinuation-748396.html&#34;&gt;Nintendo discontinued support&lt;/a&gt; for the online functionality of the News Channel.&lt;/p&gt;&#xA;&lt;p&gt;But as expected for a beloved retro console, community efforts have sprung up to try and preserve the previously existing functionality and allow users to continue enjoying these systems well past their intended expiration date. These sorts of unofficial software for gaming consoles are commonly referred to as &amp;ldquo;homebrew&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;Importantly for this project, the &lt;a href=&#34;https://wiilink.ca/#intro/&#34;&gt;WiiLink&lt;/a&gt; team maintains servers and develops software that allows us to experience the Wii&amp;rsquo;s online connectivity features even today.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;By the way, if you&amp;rsquo;re curious about how to get started with Wii console homebrew, check out &lt;a href=&#34;https://wii.hacks.guide&#34;&gt;https://wii.hacks.guide&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Thanks to WiiLink, we can &lt;a href=&#34;https://wiilink.ca/guide/news/&#34;&gt;revive the News Channel&lt;/a&gt; and browse up-to-date news! Just not the local news, which is our real goal.&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/wiilink-news-tech.png&#34; alt=&#34;wii news channel showing technology stories after patching with wiilink&#34;&gt;&#xA;&lt;h3 id=&#34;how-wiilink-patches-the-news-channel&#34;&gt;How WiiLink patches the News Channel&lt;/h3&gt;&#xA;&lt;p&gt;After going through the WiiLink install process, if we fire up &lt;code&gt;mitmproxy&lt;/code&gt; and take a look at what the Wii is doing now, we&amp;rsquo;ll see that it&amp;rsquo;s actually requesting files from a different domain: &amp;ldquo;news.wiilink.ca&amp;rdquo;. But this time, it manages to fetch &lt;code&gt;news.bin.00&lt;/code&gt; and keeps requesting files all the way up to &lt;code&gt;news.bin.23&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The News Channel just successfully fetched 24 hours worth of news from this server.&lt;/p&gt;&#xA;&lt;img class=&#34;with-border&#34; src=&#34;https://raulnegron.me/img/wiinews-pr/wiilink-requests.png&#34; alt=&#34;mitmproxy web showing HTTP requests from the Wii to http://news.wiilink.ca/v2/1/049/news.bin.00, etc.&#34;&gt;&#xA;&lt;p&gt;Great! Somehow, the WiiLink folks got this all to work. And, best of all, they&amp;rsquo;ve opened-sourced their work (&lt;a href=&#34;https://github.com/WiiLink24&#34;&gt;GitHub&lt;/a&gt;). The plan is looking really feasible at this point!&lt;/p&gt;&#xA;&lt;p&gt;At a high-level, there are two steps to tackle, then:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We have to make the News Channel fetch files from a server we control&lt;/li&gt;&#xA;&lt;li&gt;We need to actually generate binary files with the content we want&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;step-1-patching-the-news-channel-to-redirect-to-our-domain&#34;&gt;Step 1: Patching the News Channel to redirect to our domain&lt;/h2&gt;&#xA;&lt;p&gt;If we follow along with &lt;a href=&#34;https://wiilink.ca/guide/install/&#34;&gt;WiiLink&amp;rsquo;s installation guide&lt;/a&gt;, the critical step seems to be installing a patched version of the News Channel. Looking at their GitHub org, we find a &lt;a href=&#34;https://github.com/WiiLink24/WiiLink24-Patcher/&#34;&gt;WiiLink24-Patcher&lt;/a&gt; project. Searching for the &amp;ldquo;News Channel&amp;rdquo; in the source code, we find &lt;a href=&#34;https://github.com/WiiLink24/WiiLink24-Patcher/blob/033ccb9a3be574dad76f57ac82f3af226eef0fdb/WiiLink-Patcher-CLI/patch.cs#L538&#34;&gt;this line in patch.cs&lt;/a&gt; which references a &lt;a href=&#34;https://en.wikipedia.org/wiki/VCDIFF&#34;&gt;VCDIFF&lt;/a&gt; encoded &lt;code&gt;News_1.delta&lt;/code&gt; patch.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Side note - it&amp;rsquo;s only while writing this blog post that I realized I had been looking at the &amp;ldquo;wrong&amp;rdquo; repo; WiiLink&amp;rsquo;s guide now recommends using the Python-based &lt;a href=&#34;https://github.com/WiiLink24/WiiLink-Patcher-GUI&#34;&gt;WiiLink-Patcher-GUI&lt;/a&gt; instead of the CLI patcher.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;!-- &gt; This newer repo which uses a `bsdiff` based patch (see [news channel specific data](https://github.com/WiiLink24/WiiLink-Patcher-GUI/blob/master/data/patches.json#L89) in JSON, used by the [download_patch](https://github.com/WiiLink24/WiiLink-Patcher-GUI/blob/6a51dff3c28aa5d2687ff0f97c18aa2eb93f047a/setup/download.py#L274) function). --&gt;&#xA;&lt;p&gt;After downloading the &lt;code&gt;.delta&lt;/code&gt; file locally, we can use the &lt;a href=&#34;https://en.wikipedia.org/wiki/Xdelta&#34;&gt;xdelta&lt;/a&gt; CLI to print out some information on what the patch is supposed to do:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;xdelta3 printdelta News_1.delta&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VCDIFF version:               &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VCDIFF header size:           &lt;span class=&#34;m&#34;&gt;29&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VCDIFF header indicator:      VCD_APPHEADER&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VCDIFF secondary compressor:  lzma&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VCDIFF application header:    news.dol//0000000b.app/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;XDELTA filename &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;output&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:     news.dol&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;XDELTA filename &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:     0000000b.app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Okay, so we&amp;rsquo;re looking for a &lt;code&gt;0000000b.app&lt;/code&gt; file and want to save the patched binary as &lt;code&gt;news.dol&lt;/code&gt;. Based on the WiiLink install instructions, we know we should be dealing with a &lt;code&gt;WAD&lt;/code&gt; file, so let&amp;rsquo;s keep digging to see if we can find out where &lt;code&gt;0000000b.app&lt;/code&gt; might be hiding.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Learn more about the WAD file format on &lt;a href=&#34;https://wiibrew.org/wiki/WAD_files&#34;&gt;wiibrew.org&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;From the repo&amp;rsquo;s &lt;code&gt;README.md&lt;/code&gt;, we know the patcher uses &lt;a href=&#34;https://github.com/TheShadowEevee/libWiiSharp&#34;&gt;libWiiSharp&lt;/a&gt; for it&amp;rsquo;s WAD file management during the file patching processing (&lt;a href=&#34;(https://github.com/WiiLink24/WiiLink24-Patcher/blob/033ccb9a3be574dad76f57ac82f3af226eef0fdb/WiiLink-Patcher-CLI/patch.cs#L396)&#34;&gt;source&lt;/a&gt;). But at this point, I&amp;rsquo;d rather avoid using C# if I can. And besides, I know for a fact we&amp;rsquo;ll want to use Go in order to more easily leverage existing tooling from the WiiLink team.&lt;/p&gt;&#xA;&lt;p&gt;Thankfully, there&amp;rsquo;s a really handy Go library called &lt;a href=&#34;https://pkg.go.dev/github.com/wii-tools/wadlib&#34;&gt;wadlib&lt;/a&gt; that comes to the rescue here. We&amp;rsquo;ll be using it for all our WAD management needs.&lt;/p&gt;&#xA;&lt;p&gt;So, where is &lt;code&gt;0000000b.app&lt;/code&gt;? Looking at LibWiiSharp&amp;rsquo;s &lt;code&gt;WAD.cs&lt;/code&gt; file, we can spot how it unpacks &lt;code&gt;.app&lt;/code&gt; files from a WAD file. Namely, it defaults to using the numeric &amp;ldquo;Content ID&amp;rdquo; inside each &amp;ldquo;Content&amp;rdquo; metadata and then converts it to an 8-digit hexadecimal string (&lt;a href=&#34;https://github.com/TheShadowEevee/libWiiSharp/blob/23d477a3f83d0400d73393b2febde7912968b1dc/WAD.cs#L863-L874&#34;&gt;source&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;You can read more about Title metadata (&amp;ldquo;TMD&amp;rdquo;) and Content metadata (&amp;ldquo;CMD&amp;rdquo;) on &lt;a href=&#34;https://wiibrew.org/wiki/Title_metadata#Content_metadata_(CMD)&#34;&gt;wiibrew.org&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Armed with this knowledge, we can use &lt;code&gt;wadlib&lt;/code&gt; to create a quick file extraction script and see if we can find our &lt;code&gt;0000000b.app&lt;/code&gt;. It can go something like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// ignore error handling for brevity&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;wad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wadlib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;LoadWADFromFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;news.wad&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;titleMetadata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;TMD&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;contentMetadata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;titleMetadata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Contents&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;extracted_wad/&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;MkdirAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mo&#34;&gt;0755&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;GetContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentID&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentMetadata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ID&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// &amp;#34;%08x&amp;#34; means 0-padded 8 digit hex&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;filepath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%08x.app&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WriteFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mo&#34;&gt;0644&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Extracted: %08x.app (size: %d bytes)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--  ([obtainable from Vimm&#39;s lair](https://vimm.net/vault/36744)) --&gt;&#xA;&lt;p&gt;When &lt;code&gt;news.wad&lt;/code&gt; is the official (v7) News Channel WAD file, this script successfully extracts 12 &lt;code&gt;.app&lt;/code&gt; files.&lt;/p&gt;&#xA;&lt;img class=&#34;with-border&#34; src=&#34;https://raulnegron.me/img/wiinews-pr/extracted-wads.png&#34; alt=&#34;macos finder view showing extracted files&#34;&gt;&#xA;&lt;p&gt;There&amp;rsquo;s definitely a &lt;code&gt;0000000b.app&lt;/code&gt; there, but could it be the file we&amp;rsquo;re looking for?&lt;/p&gt;&#xA;&lt;p&gt;What we really need to do at this point is go ahead and apply the &lt;code&gt;News_1.delta&lt;/code&gt; patch to this &lt;code&gt;0000000b.app&lt;/code&gt; file manually. That way, we can compare the before/after binaries and see what changed. We can use &lt;code&gt;xdelta&lt;/code&gt; again to actually apply the patch. Running &lt;code&gt;xdelta3 --help&lt;/code&gt; says:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;apply patch:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  xdelta3.exe -d -s old_file delta_file decoded_new_file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So we can go ahead and run:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;xdelta3 -d -s extracted_wad/0000000b.app News_1.delta news.dol&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;hellip; seemed to work? We have a &lt;code&gt;news.dol&lt;/code&gt; file, as expected. Now what?&lt;/p&gt;&#xA;&lt;h3 id=&#34;investigating-binary-file-changes&#34;&gt;Investigating binary file changes&lt;/h3&gt;&#xA;&lt;p&gt;We could do a binary diff of these files and start going through each change, but we already know at least one thing that should have changed based on our previous &lt;code&gt;mitmproxy&lt;/code&gt; experiments: instead of performing requests to &amp;ldquo;news.wapp.wii.com&amp;rdquo;, the patched WAD should instead use &amp;ldquo;news.wiilink.ca&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;Using a tool like &lt;a href=&#34;https://hexfiend.com/&#34;&gt;Hex Fiend&lt;/a&gt; (which also has binary diffing capabilities in case we need them), we can try searching for text inside the binary. If we try searching for &amp;ldquo;news.wapp.wii.com&amp;rdquo; on the original &lt;code&gt;0000000b.app&lt;/code&gt; file, we can actually find a match!&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/original-url-in-binary.png&#34; alt=&#34;hex fiend UI showing original Wii News Channel data URL in search results&#34;&gt;&#xA;&lt;p&gt;Sure enough, if we inspect the patched &lt;code&gt;news.dol&lt;/code&gt; file we will find no mention of the original URL. Instead, the &amp;ldquo;&lt;a href=&#34;http://news.wiilink.ca&#34;&gt;http://news.wiilink.ca&lt;/a&gt;&amp;rdquo; domain is visible at the same location (offset &lt;code&gt;0x1AC37C&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/patched-url-in-binary.png&#34; alt=&#34;hex fiend UI showing modified Wii News Channel data URL in search results&#34;&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Note that the URL contains only two printf-style format strings (&lt;code&gt;%d&lt;/code&gt; and &lt;code&gt;%03d&lt;/code&gt;); the News Channel itself must be appending the hourly suffix (like &lt;code&gt;.00&lt;/code&gt;) when fetching data.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;If we&amp;rsquo;re lucky, simply overwriting the binary file&amp;rsquo;s original URL with our own custom URL might do the trick. It&amp;rsquo;s worth a try!&lt;/p&gt;&#xA;&lt;p&gt;In order to validate this hypothesis, I wrote a small Go utility for performing the necessary text replacement. Here&amp;rsquo;s an excerpt of the important bits:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// ignoring error handling for brevity&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;OriginalURL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;http://news.wapp.wii.com/v2/%d/%03d/news.bin&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;NewURL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;http://wii.rauln.com/news/%d/%03d/news.bin&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;wad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wadlib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;LoadWADFromFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wadPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Get decrypted content at index 1 (record with ID &amp;#34;0000000b&amp;#34;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;GetContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// byte slice of 44 bytes&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;originalContent&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;OriginalURL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 43 bytes in our URL&amp;#39;s case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;newContent&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;NewURL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Pad the new URL to match original length (44 bytes)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;paddedURL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;originalContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;paddedURL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Find the offset (index) of the URL to patch inside the byte slice&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;originalContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Patch the URL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;originalContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;paddedURL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;UpdateContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Save the updated WAD file&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WriteFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;outputPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wadBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mo&#34;&gt;0644&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;Check out the full source on GitHub: &lt;a href=&#34;https://github.com/rnegron/WiiNewsPR-Patcher&#34;&gt;WiiNewsPR-Patcher&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;If we run the utility like:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;go build&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wiinewspr-patcher news.wad patched_news.wad&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It should perform the URL rewriting in memory and provide us with a valid WAD file (&lt;code&gt;patched_news.wad&lt;/code&gt;) we can then go ahead and install on Wii hardware.&lt;/p&gt;&#xA;&lt;p&gt;We can install the patched WAD on our Wii console using &lt;a href=&#34;https://wii.hacks.guide/yawmme&#34;&gt;YAWM (ModMii Edition)&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/yawm-patched.png&#34; alt=&#34;yawmme showing patched WAD installation succeeded&#34;&gt;&#xA;&lt;p&gt;Finally, we can go back to running &lt;code&gt;mitmproxy&lt;/code&gt; and opening the newly patched News Channel. Once the channel shows the &amp;ldquo;Downloading&amp;hellip;&amp;rdquo; splash screen, we&amp;rsquo;ll spot requests going out to our expected domain.&lt;/p&gt;&#xA;&lt;img class=&#34;with-border&#34; src=&#34;https://raulnegron.me/img/wiinews-pr/custom-request-failed.png&#34; alt=&#34;mitmproxy showing http 404 on our custom server from a News Channel request&#34;&gt;&#xA;&lt;p&gt;It works! Now all we need is to&amp;hellip; actually generate valid news files for the News Channel to work.&lt;/p&gt;&#xA;&lt;h2 id=&#34;step-2-generating-news-channel-compatible-news-files&#34;&gt;Step 2: Generating News Channel compatible news files&lt;/h2&gt;&#xA;&lt;p&gt;I mentioned previously that I knew using Go would come in handy later, and it&amp;rsquo;s specifically because the WiiLink team has a project called &lt;a href=&#34;https://github.com/WiiLink24/NewsChannel&#34;&gt;NewsChannel&lt;/a&gt; written in Go which contains the source code for generating the binary news files they serve from &amp;ldquo;news.wiilink.ca&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not going to go over all the implementation details here. I just want to highlight some of the main file creation steps in case you&amp;rsquo;d like to read more:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;obtain country-specific configuration (&lt;a href=&#34;https://github.com/WiiLink24/NewsChannel/blob/cd676d7aa8f9b80ab9ee4fa32c21a80d3a65c38d/countries.json&#34;&gt;source&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;obtain articles and metadata from configured sources (like NHK, &lt;a href=&#34;https://github.com/WiiLink24/NewsChannel/blob/cd676d7aa8f9b80ab9ee4fa32c21a80d3a65c38d/news/nhk/articles.go#L7-L46&#34;&gt;source&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;process all data in a specific order into a bytes buffer (&lt;a href=&#34;https://github.com/WiiLink24/NewsChannel/blob/cd676d7aa8f9b80ab9ee4fa32c21a80d3a65c38d/main.go#L77-L90&#34;&gt;source&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;compress the data using LZ10, sign it with RSA, then write to disk (&lt;a href=&#34;https://github.com/WiiLink24/NewsChannel/blob/cd676d7aa8f9b80ab9ee4fa32c21a80d3a65c38d/main.go#L126-L142&#34;&gt;source&lt;/a&gt;)&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the file name is written using a specific string interpolation (&lt;a href=&#34;https://github.com/WiiLink24/NewsChannel/blob/cd676d7aa8f9b80ab9ee4fa32c21a80d3a65c38d/main.go#L108&#34;&gt;source&lt;/a&gt;, this is how I first found out about the language/country codes used in the News Channel data URL!)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Fun fact: LZ10 is apparently a Nintendo-specific variant of the &lt;a href=&#34;https://en.wikipedia.org/wiki/LZ77_and_LZ78&#34;&gt;LZ77&lt;/a&gt; compression algorithm, used in some form or another on Game Boy Advance, Nintendo DS and Wii systems. &lt;a href=&#34;https://github.com/wii-tools/lzx/blob/4c1183c96cc616e6b3312072e7f1ad984edd109f/lz10/compress.go&#34;&gt;wii-tools/lzx&lt;/a&gt; has the Go source for the LZ10 compression used here.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;In any case, for our purposes, it&amp;rsquo;s doing more than we need in terms of source handling: it can generate news binaries from a variety of sources and supports different languages and regions.&lt;/p&gt;&#xA;&lt;p&gt;For this project, I am making the following assumptions and tradeoffs:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I will be using &amp;ldquo;English&amp;rdquo; as the language and &amp;ldquo;US&amp;rdquo; as the country code for the source URL path since my Wii console is configured as such. There is no separate Puerto Rico country code option, which is curious considering that there is a separate option for the US Virgin Islands.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I am not interested in supporting any other news sources from around the world, so the &amp;ldquo;Globe&amp;rdquo; feature for the News Channel will not be useful.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I&amp;rsquo;m hardcoding the latitude and longitude of Puerto Rico&amp;rsquo;s capital into the binary file to avoid having to process or guess location data from each article entry.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;modifying-wiilinks-generator-to-support-puerto-rican-news&#34;&gt;Modifying WiiLink&amp;rsquo;s generator to support Puerto Rican news&lt;/h3&gt;&#xA;&lt;p&gt;I went ahead and forked the &lt;code&gt;NewsChannel&lt;/code&gt; repo into &lt;a href=&#34;https://github.com/rnegron/WiiNewsPR&#34;&gt;WiiNewsPR&lt;/a&gt;, added flag support to control article caching and binary output paths (you&amp;rsquo;ll see why this was necessary soon), removed all the existing sources and added a new one: &lt;a href=&#34;https://www.elnuevodia.com/&#34;&gt;El Nuevo Día (&amp;ldquo;ENDI&amp;rdquo;)&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I picked ENDI only because it&amp;rsquo;s the only local newspaper website I could find which still &lt;a href=&#34;https://www.elnuevodia.com/rss/&#34;&gt;supports RSS&lt;/a&gt;. Unfortunately, the feeds only contain a snippet of the actual article. On the bright side, most articles do contain images and we can use separate feeds to help categorize articles in the News Channel (&lt;a href=&#34;https://github.com/rnegron/WiiNewsPR/blob/11df0e242bb1f4134e61ff0b35587372a5fd0564/news/endi/articles.go#L72-L79&#34;&gt;source&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;By the way, I experimented with &lt;a href=&#34;https://github.com/advancedlogic/GoOse&#34;&gt;GoOse&lt;/a&gt; for (spanish language) article extraction on other news websites and the results were&amp;hellip; unsatisfying, to say the least.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h3 id=&#34;final-setup-requirements-for-proper-news-channel-support&#34;&gt;Final setup requirements for proper News Channel support&lt;/h3&gt;&#xA;&lt;p&gt;Two quick things we&amp;rsquo;ll need in order to get this all to work:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We need to sign each binary news file with a custom RSA key for the Wii to process the file (&lt;a href=&#34;https://github.com/rnegron/WiiNewsPR/blob/11df0e242bb1f4134e61ff0b35587372a5fd0564/utils.go#L20&#34;&gt;source&lt;/a&gt;). We can use &lt;code&gt;openssl&lt;/code&gt; for this (note the &lt;code&gt;-traditional&lt;/code&gt; option):&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; openssl genrsa -traditional -out Private.pem &lt;span class=&#34;m&#34;&gt;2048&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;We need a (really) low quality logo for our source. &lt;a href=&#34;https://imagemagick.org/script/command-line-processing.php&#34;&gt;ImageMagick&lt;/a&gt; easily solves for this:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;magick logo.svg -quality &lt;span class=&#34;m&#34;&gt;30&lt;/span&gt; -resize 200x200 -strip logo.jpg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, we can use &lt;a href=&#34;https://pkg.go.dev/embed&#34;&gt;Go embeds&lt;/a&gt; to include the logo in the Go binary (&lt;a href=&#34;https://github.com/rnegron/WiiNewsPR/blob/11df0e242bb1f4134e61ff0b35587372a5fd0564/news/endi/articles.go#L18-L19&#34;&gt;source&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;Finally, we can build the Go binary and run it in order to generate a news binary in &lt;code&gt;./v2/1/049&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;go build&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./WiiNewsPR&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This successfully generates a &lt;code&gt;news.bin.NN&lt;/code&gt; file.&lt;/p&gt;&#xA;&lt;p&gt;Now we just need 24 of these, since the News Channel will actually fail to load if not provided with all 24 files. We could run this script every hour for the next 24 hours&amp;hellip; or, we could take the shortcut of copying the current hour&amp;rsquo;s file into all other hourly values.&lt;/p&gt;&#xA;&lt;p&gt;Regardless, it&amp;rsquo;s about time to test out all this effort. With 24 files uploaded to our storage provider (AWS S3), and the patched News Channel configured to fetch these from our custom domain, we can start up the channel and observe the fruits of our labor.&lt;/p&gt;&#xA;&lt;img class=&#34;with-border&#34; src=&#34;https://raulnegron.me/img/wiinews-pr/custom-requests-success.png&#34; alt=&#34;mitmproxy showing successful http 200 requests on our custom server from a News Channel request&#34;&gt;&#xA;&lt;p&gt;After the (slow!) requests finish one by one, seeing the articles pop up was immensely satisfying. Being able to tinker with and learn more about these nostalgic consoles so many years later is a real joy for me.&lt;/p&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/wiinews-pr/wiinewspr-business-section.png&#34; alt=&#34;&#34;&gt;&#xA;&lt;h2 id=&#34;bonus-step-automating-hourly-news-updates-with-aws-lambda&#34;&gt;Bonus step: Automating hourly news updates with AWS Lambda&lt;/h2&gt;&#xA;&lt;p&gt;Copying files into the S3 storage bucket is all well and good, but it would be great to have a continuously-updating, hands-off solution that generates the news binaries for us. A simple (and basically free) way to solve for this would be to bundle up the &lt;code&gt;WiiNewsPR&lt;/code&gt; Go executable into an AWS Lambda function and have that run hourly via EventBride, and then uploading the generated news binaries over to our storage bucket.&lt;/p&gt;&#xA;&lt;p&gt;Here is where the extra flags for &lt;code&gt;WiiNewsPR&lt;/code&gt; come in: we need to be able to control file creation because &lt;code&gt;/tmp&lt;/code&gt; is a Lambda&amp;rsquo;s only writeable file system.&lt;/p&gt;&#xA;&lt;p&gt;Here is a snippet of the Lambda handler logic:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Handler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;exec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;CommandContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;./WiiNewsPR&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;-o&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/tmp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/tmp/cache&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uploader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Upload&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;PutObjectInput&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Bucket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bucketName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%snews.bin.%s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;keyPrefix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hour&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ContentType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;application/octet-stream&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lambda&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Handler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;See full Lambda handler source on GitHub: &lt;a href=&#34;https://github.com/rnegron/WiiNewsPR/blob/master/deploy/handler.go&#34;&gt;handler.go&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;We can then leverage the &lt;a href=&#34;https://www.serverless.com/&#34;&gt;Serverless&lt;/a&gt; framework for a quick infra-as-code setup. Here is a snippet of the configuration:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;wiinewspr-generator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;provider&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# ...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# ...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;TZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;America/Puerto_Rico&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# we need Lambda to generate files postfixed with the correct &amp;#34;currentHour&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# ...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;events&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;schedule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;rate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;cron(30 * * * ? *)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# run every hour:30&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;wiinewspr-every-30pasthour&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Generate Wii News PR binary file every hour at 30 minutes past&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;patterns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;bootstrap&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# compiled Lambda handler&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;WiiNewsPR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# compiled binary news generator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;../Private.pem&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# we need to include the Private.pem file for file signing&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;See full &lt;code&gt;serverless&lt;/code&gt; configuration on GitHub: &lt;a href=&#34;https://github.com/rnegron/WiiNewsPR/blob/master/deploy/serverless.yml&#34;&gt;serverless.yml&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Some things to call out here:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We want to make sure to run the Lambda in Puerto Rico&amp;rsquo;s timezone so that &lt;code&gt;time.Now()&lt;/code&gt; returns the expected hourly integer.&lt;/li&gt;&#xA;&lt;li&gt;We want to give the Lambda a higher than expected &lt;code&gt;memorySize&lt;/code&gt; so that its CPU scales accordingly; it turns out that &lt;code&gt;lz10&lt;/code&gt; compression is a big bottleneck on the smallest supported Lambda CPU and can easily time out at 30 seconds.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If we leave this setup running for 24 hours, our storage bucket will get populated with 24 files and continuously be updated with the latest news!&lt;/p&gt;&#xA;&lt;img class=&#34;with-border&#34; src=&#34;https://raulnegron.me/img/wiinews-pr/hourly-generated-files.png&#34; alt=&#34;s3 bucket view showing binary news files generated automatically at hourly intervals&#34;&gt;&#xA;&lt;p&gt;Now I can get up in the morning, grab a coffee, and browse the local news on my Nintendo Wii like it&amp;rsquo;s 2007.&lt;/p&gt;&#xA;&lt;p&gt;Thanks for reading!&lt;/p&gt;&#xA;&lt;h2 id=&#34;credits&#34;&gt;Credits&lt;/h2&gt;&#xA;&lt;p&gt;This experiment would have likely ended in disappointment if not for the amazing work by the Wii homebrew community, specifically: &lt;a href=&#34;https://github.com/riiconnect24&#34;&gt;RiiConnect24 Team&lt;/a&gt;, &lt;a href=&#34;https://github.com/wiilink24&#34;&gt;WiiLink Team&lt;/a&gt; and &lt;a href=&#34;https://wiibrew.org/wiki/Main_Page&#34;&gt;wiibrew.org Contributors&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;!--&#xA;* The `main` package contains the `news` type t&#xA;* `sources.go` defines the `GetNewsArticles` method for the `news` type, along with source-specific metadata like logo&#xA;* The [news/](https://github.com/WiiLink24/NewsChannel/tree/cd676d7aa8f9b80ab9ee4fa32c21a80d3a65c38d/news) subdirectory contains code for implement the `GetArticles`&#xA;* The News Channel reads binary files containing (created using methods like `MakeSourceTable` and `MakeArticleTable`) --&gt;&#xA;&lt;!-- ### Dolphin&#xA;&#xA;- `Tools` -&gt; `Perform Online System Update`&#xA;&#xA;- `Tools` -&gt; `Install WAD...`&#xA;&#xA;- `Tools` -&gt; `Load Wii System Menu 4.3U`&#xA;&#xA;The Dolphin emulator&#xA;&#xA;- Enable System Menu and update --&gt;&#xA;</description>
			</item>
			<item>
				<title>Getting started with Game Boy development on Mac</title>
				<link>https://raulnegron.me/2018/starting-gb-dev/</link>
				<pubDate>Sat, 21 Apr 2018 00:00:00 +0000</pubDate>
				<guid>https://raulnegron.me/2018/starting-gb-dev/</guid>
				<description>&lt;br&gt;&#xA;&lt;center&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/gameboy.jpg&#34; style=&#34;width: 170px;&#34;/&gt;&#xA;&lt;/center&gt;&#xA;&lt;br&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t know what inspired it, but recently I got the idea that programming for an old game console would make for a fun project. Apart from giving me an excuse to write code in a language other than Python, it&amp;rsquo;s something I&amp;rsquo;ve wanted to do ever since I learned that programming was at the heart of all the great games I&amp;rsquo;ve played throughout the years. So, I decided to find out how feasible it would be to program for one of these old school gaming systems.&lt;/p&gt;&#xA;&lt;p&gt;The Game Boy Advance was my first research subject. While reading up on the GBA, I learned that the original Game Boy (model &amp;ldquo;DMG-01&amp;rdquo;) had a more well-established homebrew community, compared to the Game Boy Advance. There is a lot of great documentation out there on developing for the Game Boy! Just visiting the &lt;a href=&#34;https://github.com/avivace/awesome-gbdev&#34;&gt;awesome-gbdev&lt;/a&gt; repo convinced me to choose the original Game Boy as my retro coding platform.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;d like to blog about my experience as a form of self-motivation. I&amp;rsquo;ll write about the process from the start and then be able to look back and see how I&amp;rsquo;ve progressed along the way! And if someone happens upon these posts, I hope they find them useful.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: I&amp;rsquo;ll be using the following Japanese-language blog post as a template for this one: &lt;a href=&#34;https://qiita.com/syano/items/2180da2cfe9ce161e65b&#34;&gt;開発環境の導入&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h1 id=&#34;development-environment-on-macos&#34;&gt;Development Environment on MacOS&lt;/h1&gt;&#xA;&lt;p&gt;As the title says, I am working towards a functional GB dev environment on MacOS (specifically High Sierra, version 10.13.4). Sadly, most of the good tools for Game Boy development are Windows-only. But that&amp;rsquo;s okay! We can get away with using &lt;a href=&#34;https://www.winehq.org/&#34;&gt;Wine&lt;/a&gt; to run the best of them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;an-introduction-to-the-tools&#34;&gt;An introduction to the tools&lt;/h2&gt;&#xA;&lt;p&gt;The development scene for the Game Boy is centered around two programming languages: C and assembly. My personal preference was to start developing in C. I&amp;rsquo;m using Harry Mulder&amp;rsquo;s &lt;a href=&#34;http://www.devrs.com/gb/hmgd/gbtd.html&#34;&gt;Tile Designer&lt;/a&gt; as well as his &lt;a href=&#34;http://www.devrs.com/gb/hmgd/gbmb.html&#34;&gt;Map Builder&lt;/a&gt; to manage the graphical aspects of developing for a video game console. Finally, the &lt;a href=&#34;http://bgb.bircd.org/&#34;&gt;bgb&lt;/a&gt; emulator is the standard for testing and debugging Game Boy games.&lt;/p&gt;&#xA;&lt;h1 id=&#34;getting-a-c-compiler-up-and-running&#34;&gt;Getting a C compiler up and running:&lt;/h1&gt;&#xA;&lt;p&gt;The tool of choice here is the &lt;a href=&#34;http://gbdk.sourceforge.net/&#34;&gt;Game Boy Developers Kit&lt;/a&gt; (GBDK). The installation may be tricky on MacOS. There are a couple of alternative installation methods around, but I went for the following:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ git clone https://github.com/x43x61x69/gbdk-osx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; gbdk-osx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ mkdir -p sdcc/bin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ sed -i &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; -e &lt;span class=&#34;s1&#34;&gt;&amp;#39;1005d&amp;#39;&lt;/span&gt; sdcc/src/SDCC.y&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ make&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ sudo mkdir /opt &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo cp -r build/ppc-unknown-linux2.2/gbdk /opt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;make&lt;/code&gt; will proceed to build GBDK. Note that the above commands do some extra stuff besides building the compiler libraries. Click on them below to learn more about why they are required if we want the build to succeed.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/co-me/gbdk/issues/1&#34;&gt;&lt;code&gt;mkdir -p sdcc/bin&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/x43x61x69/gbdk-osx/issues/2&#34;&gt;&lt;code&gt;sed -i &#39;&#39; -e &#39;1005d&#39; sdcc/src/SDCC.y&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/co-me/gbdk/issues/5&#34;&gt;&lt;code&gt;sudo mkdir /opt &amp;amp;&amp;amp; sudo cp -r build/ppc-unknown-linux2.2/gbdk /opt&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Make sure to add the path to the new binaries to your &lt;code&gt;PATH&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/opt/gbdk/bin:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ideally, you would include that line in your &lt;code&gt;.bash_profile&lt;/code&gt; or similar. The compiler&amp;rsquo;s front-end (called &lt;code&gt;lcc&lt;/code&gt;) would then be easily accessible.&lt;/p&gt;&#xA;&lt;p&gt;You could also choose to leave the binaries in-place and make a symbolic link, like so:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ sudo ln -s build/ppc-unknown-linux2.2/gbdk /opt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In that case, you would have to adjust your &lt;code&gt;PATH&lt;/code&gt; accordingly.&lt;/p&gt;&#xA;&lt;h1 id=&#34;building-a-minimal-game-boy-game-a-sanity-check&#34;&gt;Building a minimal Game Boy game: a sanity check&lt;/h1&gt;&#xA;&lt;p&gt;Having come this far, let&amp;rsquo;s make something a bit more involved than a &lt;code&gt;printf(&amp;quot;Hello, world!&amp;quot;);&lt;/code&gt; for the Game Boy, shall we?&lt;/p&gt;&#xA;&lt;p&gt;Create a file and then copy-paste (or type by hand!) the following code:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt; &#x9;// printf(), delay()&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;gb/gb.h&amp;gt;  // joypad(), J_UP, J_DOWN, ...&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;// Loop forever&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// Check the status of the Game Boy Joy Pad&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;switch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;joypad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// If the UP button is pressed...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;J_UP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// Display &amp;#34;Up!&amp;#34; on the screen&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Up!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// Then wait for half a second...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// Go back to checking the status of the Joy Pad&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// And so on&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;J_DOWN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Down!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;J_LEFT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Left!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;J_RIGHT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Right!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Save the file as &lt;code&gt;first.c&lt;/code&gt; and proceed to build the code:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ lcc first.c -o first.gb&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hopefully everything compiled correctly! You&amp;rsquo;ll know it worked if &lt;code&gt;lcc&lt;/code&gt; stays quiet after compiling, thus obeying &lt;a href=&#34;http://www.linfo.org/rule_of_silence.html&#34;&gt;The Rule of Silence&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s run &lt;em&gt;bgb&lt;/em&gt; (&lt;code&gt;$ wine bgb.exe&lt;/code&gt;), secondary-click the window, open &lt;code&gt;first.gb&lt;/code&gt; and check out the results!&lt;/p&gt;&#xA;&lt;br&gt;&#xA;&lt;center&gt;&#xA;&lt;img src=&#34;https://raulnegron.me/img/gb-1-bgb-1.png&#34; style=&#34;width: 250px;&#34;/&gt;&#xA;&lt;/center&gt;&#xA;&lt;br&gt;&#xA;&lt;p&gt;And that&amp;rsquo;s it! From code to binary that the Game Boy recognizes, built on MacOS. A world of 8-bit possibilities awaits! A more complete version of this example is available at &lt;a href=&#34;http://gbdev.gg8.se/wiki/articles/GBDK_Joypad_Tutorial&#34;&gt;GBDev&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-c-alternative-rgbds-on-macos&#34;&gt;The C alternative: RGBDS on MacOS&lt;/h2&gt;&#xA;&lt;p&gt;This post focused on coding in C. For assembly, there exists the &lt;a href=&#34;https://github.com/rednex/rgbds&#34;&gt;Rednex Game Boy Development System (RGBDS)&lt;/a&gt;.&#xA;The best part is that installation couldn&amp;rsquo;t be simpler.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ brew install rgbds&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I will definitely get into assembly on the GB at some point in the future!&lt;/p&gt;&#xA;&lt;h1 id=&#34;further-reading&#34;&gt;Further reading&lt;/h1&gt;&#xA;&lt;p&gt;If you can read Japanese (or don&amp;rsquo;t mind using Google Translate), I recommend the &lt;a href=&#34;https://adventar.org/calendars/2505&#34;&gt;Game Boy Advent Calendar 2017&lt;/a&gt; series of blog posts.&lt;/p&gt;&#xA;&lt;p&gt;Finally, having already mentioned the place to get a lot of good resources (&lt;a href=&#34;https://github.com/gbdev/awesome-gbdev&#34;&gt;awesome-gbdev&lt;/a&gt;), I&amp;rsquo;ll go ahead and highlight a few resources on that list.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://media.ccc.de/v/33c3-8029-the_ultimate_game_boy_talk&#34;&gt;The Ultimate Game Boy Talk&lt;/a&gt; - A must-watch deep-dive tech-talk on the original Game Boy.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/mrombout/gbdk_playground&#34;&gt;Simplified GBDK Examples&lt;/a&gt; - Repository containing self-contained examples on GBDK concepts. If you&amp;rsquo;d like to see the &lt;code&gt;printf(&amp;quot;Hello, world!&amp;quot;);&lt;/code&gt; of the Game Boy world, &lt;a href=&#34;https://github.com/mrombout/gbdk_playground/tree/master/hello_world&#34;&gt;look no further!&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/pashutk/flappybird-gameboy&#34;&gt;flappybird-gameboy&lt;/a&gt; - Reading the source code of other projects is a good way to get started with development in any environment. Flappy Bird is a simple enough game to make for a good first look into GB development in C using GBDK!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://sameboy.github.io/&#34;&gt;SameBoy&lt;/a&gt; - An active, open-source emulator written in C with a focus on MacOS support. With its debugging features, it has the potential to become the go-to emulator for development purposes on Mac!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.gamasutra.com/blogs/DoctorLudos/20171207/311143/Making_a_Game_Boy_game_in_2017_A_quotSheep_It_Upquot_PostMortem_part_12.php&#34;&gt;Making a Game Boy game in 2017: A &amp;ldquo;Sheep It Up!&amp;rdquo; Post-Mortem&amp;quot;&lt;/a&gt; - A great read chronicling the development of a Game Boy game which introduces plenty of helpful concepts along the way&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h1 id=&#34;extra-happy-29th&#34;&gt;Extra: Happy 29th!&lt;/h1&gt;&#xA;&lt;p&gt;Without realizing it, I uploaded this post on the &lt;a href=&#34;https://twitter.com/OnThisDayGaming/status/987792880260575232&#34;&gt;on the 29th anniversary&lt;/a&gt; of the Game Boy&amp;rsquo;s Japanese release date! Since I was not aware of the Game Boy&amp;rsquo;s Japanese release date, there was a $\frac{1}{365} = 0.0027%$ chance of this happening! However, taking into account the time-zone difference, I actually uploaded this post at around 7:30AM on the 22nd, Japan time. Oh well, pretty cool in any case!&lt;/p&gt;&#xA;</description>
			</item>
	</channel>
</rss>
