<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://rileytestut.com/feed.xml" rel="self" type="application/atom+xml" /><link href="http://rileytestut.com/" rel="alternate" type="text/html" /><updated>2026-03-19T21:43:18+00:00</updated><id>http://rileytestut.com/feed.xml</id><title type="html">Riley Testut</title><subtitle>Independent iOS Developer Blog</subtitle><entry><title type="html">Evolving AltStore PAL</title><link href="http://rileytestut.com/blog/2025/10/07/evolving-altstore-pal/" rel="alternate" type="text/html" title="Evolving AltStore PAL" /><published>2025-10-07T00:00:00+00:00</published><updated>2025-10-07T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2025/10/07/evolving-altstore-pal</id><content type="html" xml:base="http://rileytestut.com/blog/2025/10/07/evolving-altstore-pal/"><![CDATA[<p>In April of last year, we <a href="http://rileytestut.com/blog/2024/04/17/introducing-altstore-pal/">launched AltStore PAL</a> in the European Union as one of the first official alternative app marketplaces on iOS thanks to the Digital Markets Act. We launched with just 2 apps — my Nintendo emulator <a href="https://faq.deltaemulator.com/">Delta</a> and clipboard manager <a href="https://www.macstories.net/reviews/altstores-clip-is-the-best-clipboard-manager-on-ios-yet/">Clip</a> — yet Apple immediately <a href="https://www.macrumors.com/2024/04/17/what-to-know-about-iphone-app-store-emulators/">changed their App Store rules to allow emulators</a> worldwide for the first time ever.</p>

<p>Competition, imagine that!</p>

<p>Since then, my co-founder <a href="https://www.threads.com/@shanegill.io">Shane Gill</a> and I have continued to evolve AltStore PAL and open up the iOS app ecosystem to entirely new kinds of apps. In just our first year:</p>

<ul>
  <li>We launched <a href="https://www.theverge.com/2024/7/24/24205036/iphone-ios-torrenting-apps-eu-altstore-pal">3rd-party apps in AltStore PAL</a> in July 2024, including the first iOS torrenting apps and the virtual machine app <a href="https://getutm.app">UTM</a>. In response, Apple changed their App Store rules <a href="https://www.theverge.com/2024/7/13/24198015/apple-utm-se-pc-os-emulator-for-ios">to allow virtual machines</a> — the <em>second time</em> they’ve changed their rules in response to competition from AltStore — allowing everyone worldwide to run Windows on their iPad.</li>
  <li>In August 2024, we <a href="https://www.macrumors.com/2024/07/25/fortnite-altstore-eu/">partnered with Epic Games</a> to bring Fortnite and their other mobile games to AltStore PAL. As part of this partnership, Epic also agreed to <a href="https://www.theverge.com/2024/8/14/24220623/altstore-pal-third-party-app-store-drops-subscription-epic-grant">cover the €0.50 “Core Technology Fee”</a> Apple charges us for each download of AltStore PAL, allowing us to make AltStore entirely free to use.</li>
  <li>Earlier this year, we published Hot Tub, the first <a href="https://youtu.be/2YUgW7o6sig?t=10m50s">pornography app available on iOS</a>. Despite being easily accessible in Safari, porn is something <a href="https://www.apple.com/newsroom/2025/09/the-digital-markets-acts-impacts-on-eu-users/">Apple wants you to believe</a> is incredibly dangerous — unless of course you’re Elon Musk, in which case it’s totally fine that your AI app can <a href="https://www.theverge.com/report/718975/xai-grok-imagine-taylor-swifty-deepfake-nudes">generate nude deepfakes of Taylor Swift</a> despite being rated 13+.</li>
  <li>Finally, in April we announced our <a href="https://faq.altstore.io/developers/distribute-with-altstore-pal">self-publishing process</a>. This allowed developers to publish their apps for free on AltStore PAL without any involvement from us. Thanks to this, we now have <strong>over 100 self-published apps in AltStore</strong> — and we’re just getting started.</li>
</ul>

<p>To sum up, it’s been a wild year! Now that we’ve had some time to catch our breath however, I’m excited to share some big announcements regarding our plans for the next year — including some additional funding we’ve received to accomplish these goals and keep growing AltStore sustainably.</p>

<p>So without further adieu…</p>

<h3 id="a-global-app-store">A Global App Store</h3>

<p>By far our number one request, we’re planning to launch AltStore PAL in more countries <strong>later this year</strong> in response to various regulatory changes around the world. Specifically, we plan to launch in <strong>Japan, Brazil, and Australia</strong> before the end of the year, with the <strong>UK</strong> to follow in 2026. This is great news for the fight to open app distribution, as it will give consumers more options to install apps they otherwise couldn’t from the App Store — such as my <a href="https://www.macstories.net/reviews/altstores-clip-is-the-best-clipboard-manager-on-ios-yet/">clipboard manager Clip</a>.</p>

<p>While we wait to hear more from Apple on exact timing, if you’re a developer interested in distributing your app through AltStore PAL in one of these countries feel free to <a href="https://faq.altstore.io/developers/distribute-with-altstore-pal">check out our documentation</a> now to get a head start. Overall though, we couldn’t be more excited to make AltStore PAL available to millions of more people; we truly believe it’s a matter of time before alternative app marketplaces are available worldwide, and each new country brings us one step closer to that goal.</p>

<h3 id="a-federated-app-store">A Federated App Store</h3>

<p>A few years ago, Shane and I joined <a href="https://joinmastodon.org">Mastodon</a> along with many others in the Apple community who wanted a break from Twitter. For those that don’t know, Mastodon is part of the open social web (also known as the “Fediverse”); a collection of independent, decentralized social networks that can interoperate with each other. Other popular examples include <a href="https://www.threads.com">Threads</a> and <a href="https://bsky.app">Bluesky</a>. However, the underlying protocols that enable this interoperability — ActivityPub and AT Proto, for the nerds — support <em>far</em> more than just social media posts; they can support virtually any form of media.</p>

<p>So what about apps?</p>

<p>I’m sure you see where this is going. Today, I’m <em>thrilled</em> to announce <strong>AltStore is officially joining the Fediverse</strong> 🥳</p>

<p>Using ActivityPub, we plan to federate apps, app updates, and news alerts from AltStore to the open social web. Each AltStore source will receive its own ActivityPub account, which can then be followed by any other open social web account. You’ll be able to like, boost, and reply to everything, and most importantly <strong>all these interactions will appear natively in AltStore</strong>. In other words, you’ll be able to comment on an app on Mastodon, like a news update on Threads, then open AltStore and view all these same interactions in-app. Even better, if you login with your open social web account you can comment, like, and boost right from within AltStore!</p>

<p>Behind the scenes, we’ve <a href="https://joinmastodon.org/hosting">partnered with Mastodon gGmbH</a> to manage a custom Mastodon server on our behalf, and also with <a href="https://www.anew.social">A New Social</a> to natively support Bluesky via <a href="https://fed.brid.gy">Bridgy Fed</a>. Initially we’ll be shoe-horning all apps/updates/news alerts into toots (i.e. ActivityPub’s “Note”) for maximum compatibility, but long-term we plan to publish hypothetical new “SoftwareRelease” ActivityPub objects which could then be understood natively by other Fediverse clients — including other app marketplaces!</p>

<p>We plan to add these features to AltStore PAL in the next few months — but to celebrate our first appearance at <a href="https://fediforum.org">FediForum</a> we’re making our Mastodon server <strong>available TODAY in beta at <a href="https://explore.alt.store">explore.alt.store</a></strong> 🎉 We’ve included a few popular sources from the community to start; you can view a complete up-to-date list of all federated AltStore sources <a href="https://explore.alt.store/directory">here</a>. And if you’re a developer and want to know how to start federating your own AltStore PAL source, <a href="https://faq.altstore.io/developers/distribute-with-altstore-pal#make-your-source-discoverable-optional">check out our FAQ</a>.</p>

<p>As we iron out the kinks we’d love your feedback on how we can make the experience as nice as possible, so please send your feedback to us on <a href="https://fosstodon.org/@altstore">Mastodon</a>, <a href="https://www.threads.com/@altstoreio">Threads</a>, or <a href="https://bsky.app/profile/altstore.io">Bluesky</a> 🙂</p>

<p><img title="AltStore PAL Fediverse Integration" src="https://github.com/user-attachments/assets/1e02f2ac-1cee-4efd-aed3-d367e9358221" width="1920px" /><br />
<em>An update to AltStore PAL with native Fediverse integration is coming soon.</em></p>

<h3 id="an-enduring-app-store">An Enduring App Store</h3>

<p>By partnering with Mastodon and A New Social directly, we’re able to offload much of the added complexity of connecting AltStore to the Fediverse and focus on what we know best: building great apps. This is critical because as just a 2-person team, my co-founder Shane and I need to be careful about managing our time and not over-exerting ourselves.</p>

<p>For context, Shane and I have been working on AltStore full-time for over 5 years now funded entirely by donations to <a href="https://patreon.com/rileyshane">our Patreon</a>. This has worked better than I ever could have imagined, and I’m so incredibly thankful for our patrons. However, the reality is Shane and I are starting to reach the limits of what we can realistically accomplish as just 2 people without burning ourselves out — and that’s <em>before</em> connecting AltStore PAL to the Fediverse or expanding to new countries. As amazing as it’s been to have a sustainable Patreon, we simply can’t afford to hire a 3rd person, let alone a full team.</p>

<p>Enter Chris Paik.</p>

<p>We first met Chris a few years ago after he sideloaded <a href="https://paperback.moe/">Paperback</a> — an excellent manga reader — with AltStore Classic. He was incredibly excited by what we were building and wanted to offer us whatever help he could. It turns out he was an early investor in Patreon and Twitch — and current member of Patreon’s board — so he had plenty of experience with creator-focused projects. Since then we’ve kept in touch and asked him for advice on several occasions; the more we talked with him, the more clear it became how aligned we all were regarding what AltStore could be.</p>

<p>Fast forward to earlier this year, when I came across an <a href="https://werd.io/lets-fund-the-open-social-web/">excellent blog post by Ben Werdmuller</a> titled “Let’s fund the open social web.” In it, Ben makes a strong case for the need to start thinking seriously about building sustainable businesses if we want the open social web to succeed, and how that requires funding. He then goes on to describe the many ways of funding projects, with the bootstrapping section hitting especially close to home:</p>

<blockquote>
  <p>Bootstrapping is financially conservative, but emotionally intense. You carry all the risk, and early mistakes can cost you months — or <em>everything</em>. Without funding, you may struggle to hire help, pay yourself, or scale infrastructure. And while you own 100% of the business, you also carry 100% of the stress.</p>
</blockquote>

<p>This is exactly the situation we found ourselves in with AltStore. We were putting everything we could into the company, but fundamentally we weren’t able to hire more help or scale our operations beyond the essentials and that was severely limiting us. As long as we were reliant on Patreon donations we’d be facing these constraints, and we realized that needed to change if we wanted to ensure AltStore can survive long-term and actively compete with emerging app stores as alternative marketplaces spread worldwide.</p>

<p>So after considering all our options, we decided to reach out to Chris. He had recently started his own investment firm <a href="https://pacecapital.com">Pace Capital</a>, so we pitched him our plan to join the Fediverse and expand into new countries. We asked if he’d be willing to invest in us so we could make it a reality — and he was fully on board.</p>

<p>tl;dr:</p>

<ul>
  <li>Pace Capital is investing <strong>$6 million USD</strong> in AltStore in exchange for 15% equity. We will use this money to hire a few employees and build out a team, giving us the necessary bandwidth to finalize Fediverse integration and expand AltStore worldwide, while also releasing betas and app updates on a more regular basis.</li>
  <li>We’re transitioning from an LLC to a <strong>public benefit corporation (PBC)</strong>. This ensures our incentives are always aligned with our core mission: empowering developers to freely distribute their apps on the open web.</li>
  <li>Flipboard CEO <a href="https://flipboard.social/@mike">Mike McCue</a> will be joining our newly formed Board of Directors in addition to Chris, Shane, and myself to help guide us on our approach to embracing the open social web. Flipboard and his new app <a href="https://about.surf.social/">Surf</a> are right at the forefront of the open social web movement, so I couldn’t be happier to have someone with Mike’s experience to help us build the world’s first federated app store!</li>
</ul>

<p>With a full team and Chris and Mike on board, I’m confident we’ll have the guidance and bandwidth we need to evolve AltStore into an enduring, global, federated app store. That being said, I want to make it clear that this does <em>not</em> include Delta (or Clip). Delta remains entirely owned by me, and we’ll continue to work on it full-time as one of AltStore’s flagship apps. It <em>does</em> however mean Delta will receive updates more frequently going forward as we expand the team, especially as we work towards releasing Delta 2.0 later this year.</p>

<hr />

<p>While this helps solve our problems, it’s clear we’re far from the only open social web project that could use some funding. A rising tide lifts all boats, and because we believe the success of AltStore is intimately tied with the success of the open social web we wanted to do what we could to help ensure its long-term success.</p>

<p>So to give back to the open social web, we’re also donating a total of <strong>$500,000 to various Fediverse-related projects</strong>. This includes $300,000 to Mastodon gGmbH to thank them for their incredible stewardship of the entire ecosystem, with the remainder being split between the following incredible projects. The Fediverse as we know it today would not exist without them, so I recommend checking them all out!</p>

<p><a href="https://fed.brid.gy">Bridgy Fed</a> by <a href="https://www.anew.social">A New Social</a><br />
<a href="https://tapbots.com/ivory/">Ivory</a> + <a href="https://tapbots.com/phoenix/">Phoenix</a> by <a href="https://tapbots.com">Tapbots</a><br />
<a href="https://usetapestry.com">Tapestry</a> by <a href="https://iconfactory.com">the Iconfactory</a><br />
<a href="https://mstdn.social">mstdn.social</a><br />
<a href="https://akkoma.social">Akkoma</a><br />
<a href="https://joinpeertube.org">PeerTube</a><br />
<a href="https://bookwyrm.social">Bookwyrm</a><br />
<a href="https://fedify.dev">Fedify</a></p>

<hr />

<p>Between expanding to more countries and adding deep Fediverse integration, the next year will be an incredibly exciting time for AltStore. In just one year AltStore PAL has already pressured Apple to make several positive changes to the iOS app ecosystem, and we plan to continue doing everything we can to make the platform better for consumers and developers alike.</p>

<p>Alternative app marketplaces are needed more than ever now, with new reasons for them popping up <a href="https://www.npr.org/2025/10/03/nx-s1-5561999/apple-google-iceblock-app-removal">every week</a>. If there’s one constant though, it’s that Apple <a href="https://rileytestut.com/blog/2020/10/14/thoughts-on-app-store/">simply cannot be trusted</a> to be the sole distributor of apps on the iOS platform. Thanks to the DMA Apple’s tight grip over developers has finally been loosened, and as more countries pass their own laws allowing alternative app marketplaces we’ll continue to expand AltStore PAL and do our best to open up the iOS app ecosystem as much as possible — while federating everything as we go!</p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="altstore" /><category term="fediverse" /><summary type="html"><![CDATA[In April of last year, we launched AltStore PAL in the European Union as one of the first official alternative app marketplaces on iOS thanks to the Digital Markets Act. We launched with just 2 apps — my Nintendo emulator Delta and clipboard manager Clip — yet Apple immediately changed their App Store rules to allow emulators worldwide for the first time ever.]]></summary></entry><entry><title type="html">Introducing AltStore PAL</title><link href="http://rileytestut.com/blog/2024/04/17/introducing-altstore-pal/" rel="alternate" type="text/html" title="Introducing AltStore PAL" /><published>2024-04-17T00:00:00+00:00</published><updated>2024-04-17T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2024/04/17/introducing-altstore-pal</id><content type="html" xml:base="http://rileytestut.com/blog/2024/04/17/introducing-altstore-pal/"><![CDATA[<p>This is a day I’ve been looking forward to for <a href="https://rileytestut.com/blog/2024/02/19/happy-10-birthday-gba4ios/">over 10 years</a>.</p>

<p>I’m thrilled to announce a brand new version of AltStore — AltStore PAL — is launching <strong>TODAY</strong> as an Apple-approved alternative app marketplace in the EU. AltStore PAL is an <a href="https://github.com/altstoreio/AltStore">open-source</a> app store made specifically for independent developers, designed to address the problems I and so many others have had with the App Store over the years. Basically, if you’ve ever experienced issues with App Review, this is for you!</p>

<p>We’re launching with <strong>2 apps</strong> initially: my all-in-one Nintendo emulator <a href="https://deltaemulator.com">Delta</a> — a.k.a. the reason I built AltStore <a href="http://rileytestut.com/blog/2019/09/25/introducing-altstore/">in the first place</a> — and my clipboard manager <a href="https://rileytestut.com/blog/2020/06/17/introducing-clip/">Clip</a>, a <em>real</em> clipboard manager that can actually run in the background. Delta will be <strong>FREE</strong> (with no ads!), whereas Clip will require a small donation of <strong>€1 or more</strong>. Once we’re sure everything is running smoothly we’ll then open the doors to third-party apps — so if you’d like to distribute your app with AltStore, please <a href="mailto:apps@altstore.io">get in touch</a>.</p>

<p>And that’s the gist! Europeans running iOS 17.4 or later can now install AltStore PAL directly from the <a href="https://altstore.io">AltStore website</a>, bringing entirely new apps to iOS for the first time ever — including, of course, Delta. This has been a personal dream of mine ever since I started building emulators for iOS over a decade ago, and is what my co-founder <a href="https://www.threads.net/@shanegill.io">Shane Gill</a> and I have been working towards since launching AltStore almost 5 years ago. It truly doesn’t seem real that starting today people can <em>finally</em> use Delta as a real app, and I can’t wait for y’all to experience it 💜</p>

<p><img title="Delta's AltStore store page" src="../../../../../assets/images/posts/altstore/delta_store_page.png" width="50%" />
<br />
<em>Delta’s store page in AltStore PAL.</em></p>

<h2 id="sideloading-for-everyone">Sideloading For Everyone</h2>

<p>Unlike the App Store, all apps on AltStore are <strong>self-hosted.</strong> Once an app has been notarized by Apple, developers can download the processed “alternative distribution packet” (ADP) and upload it to their own server. To then distribute with AltStore, a developer just needs to create a “source” — which is just a JSON file containing basic app metadata uploaded to a public URL. Users must then add this source to their AltStore, after which all apps from that source will automatically appear for them to download.</p>

<p>Sources are integral to AltStore’s design and allow it to be completely <em>decentralized.</em> This means there is <strong>no central directory of apps</strong>; the only apps you’ll see in AltStore are from sources you’ve explicitly added yourself. It’s up to developers to self-promote their apps and direct users to their websites, where users can add their source with a single tap via AltStore’s <code class="language-plaintext highlighter-rouge">altstore://source?url=[source URL]</code> URL scheme (or by copying &amp; pasting the source URL directly). Distributing apps with AltStore is also <strong>completely free of charge</strong> — <em>anyone</em> can distribute an app for free on AltStore as long as they make a source.</p>

<p>If you think this all sounds similar to Apple’s recently announced <a href="https://developer.apple.com/support/web-distribution-eu/">Web Distribution</a> feature…that’s because it is! In fact, you can think of AltStore not as an app marketplace, but more as a glorified “sideloading tool” that simply reads JSON files and automatically notifies users of app updates. If you’ve ever used <a href="https://sparkle-project.org">Sparkle</a> on macOS, sources are <em>very</em> similar conceptually to a Sparkle XML file — except in addition to releasing app updates, you also use them to customize your app’s store page in AltStore.</p>

<p>Thanks to sources, distributing apps with AltStore is <strong>entirely in your control</strong> — <em>you</em> decide when to publish new app versions by choosing when to upload your updated source JSON. Of course there’s a bunch more you can do with sources, so we’ve updated the AltStore FAQ with <a href="https://faq.altstore.io/distribute-your-apps/make-a-source">complete documentation</a> on the source JSON format.</p>

<p><img title="AltStore's default source page." src="../../../../../assets/images/posts/altstore/altstore_source.png" width="50%" />
<br />
<em>You can customize your source page with your own personal branding.</em></p>

<h2 id="what-kinds-of-apps-belong-on-altstore">What kinds of apps belong on AltStore?</h2>

<p>All apps are welcome, but I believe AltStore makes the most sense for smaller, indie apps that otherwise couldn’t exist due to App Store rules. There are <em>countless</em> examples of these that aren’t allowed in the App Store for one reason or another; we just don’t know about them because there’s never been a distribution option for these poor apps.</p>

<p>One of the most popular apps on AltStore today is <a href="https://getutm.app">UTM</a>, a full-featured virtual machine for iOS and iPadOS. You can use it to <a href="https://www.youtube.com/watch?v=LrLDKYFyLMM">literally run Windows on your iPad</a>. Unfortunately <a href="https://developer.apple.com/app-store/review/guidelines/#intellectual-property">App Review Guideline 5.2</a> forbids apps from using “protected third-party material such as trademarks, copyrighted works, or patented ideas in your app without permission”, which — you guessed it — includes Windows.</p>

<p>Or take <a href="https://github.com/zzanehip/The-OldOS-Project">OldOS</a>, a beautifully-made recreation of iOS 4 built entirely in SwiftUI. Clearly a labor of love that does no one any harm, but it’s not allowed in the App Store because it “appears confusingly similar to an existing Apple product, interface, [or] app” (<a href="https://developer.apple.com/app-store/review/guidelines/#intellectual-property">5.2.5</a>).</p>

<p>Or for an even simpler example, <a href="https://github.com/willhains/Kotoba">Kotoba</a> is literally just the built-in iOS dictionary repackaged into a standalone, easy-to-use app. Yet even <em>it’s</em> not allowed because apps can only display third-party content if “you are specifically permitted to do so under the service’s terms of use” (<a href="https://developer.apple.com/app-store/review/guidelines/#intellectual-property">5.2.2</a>)…which apparently does not include the iOS system dictionary ¯\_(ツ)_/¯</p>

<!-- The above emoticon is not particularly well-suited for Markdown, alas. -->

<p>And then there’s the app my high school asked me to build to promote their upcoming 5K. I spent <em>months</em> of my sophomore year working on it…yet in the end it was rejected because it did “not provide enough of an engaging and lasting iOS specific user experience that is different from that of a web browser” (<a href="https://developer.apple.com/app-store/review/guidelines/#minimum-functionality">4.2</a>), crushing my 16-year-old self 🥲</p>

<p>I’m sure you get the point. Not all apps are rejected for interesting reasons; sometimes people just want to make cool things that don’t fully align with Apple’s goals. Our hope with AltStore is to give apps like these another path forward. We think iOS as a whole could benefit greatly from giving developers a chance to fully explore their ideas without arbitrary restrictions, and now that the App Store has real competition, we’re hopeful Apple will feel pressured to allow apps they otherwise wouldn’t.</p>

<p>And in fact…that’s already happened! Just recently, Apple updated their App Review Guidelines to <a href="https://www.theverge.com/2024/4/5/24122341/apple-app-store-game-emulators-super-apps">officially allow retro game emulators</a> like Delta — a perfect example of a competitive market at work. To be clear, <strong>this never would have happened if it wasn’t for the Digital Markets Act</strong>, and proves competition can, in fact, pressure Apple to make the App Store better for everyone. I’m hopeful we’ll see even more rule changes soon as Apple realizes all the <del>money</del> ideas they’ve been missing out on (looking at you, clipboard managers!).</p>

<p><img title="OldOS' Home Screen" src="../../../../../assets/images/posts/altstore/oldos_home.png" width="50%" />
<br />
<em>OldOS recreates the exact look and feel of iOS 4 — including a virtual home button!</em></p>

<h2 id="will-there-be-paid-apps">Will there be paid apps?</h2>

<p>Of course, this is an app <del>store</del> marketplace after all! However, we’re doing something a little different: it’s all based around Patreon donations.</p>

<p>In addition to content restrictions, the App Store also forbids certain business models — such as distributing betas “in exchange for compensation of any kind, <em>including as a reward for crowd-sourced funding.</em>” (<a href="(https://developer.apple.com/app-store/review/guidelines/#beta-testing)">2.2</a>). This is unfortunate, because not only is this a proven way to monetize software in other markets, but since launching <a href="http://rileytestut.com/blog/2019/09/25/introducing-altstore/">5 years ago</a> AltStore and Delta have been <em>entirely</em> funded by doing exactly this and providing pre-release access to our patrons through <a href="https://patreon.com/rileyshane">our Patreon</a>.</p>

<p>I strongly believe this business model works well — especially for indie developers — so we’ve gone all-in and added deep Patreon integration to AltStore to allow all developers to monetize their apps the same way we do. Developers can choose to offer some (or all) of their apps to just their patrons, and even control which tiers unlock which apps on a per-app basis. And to further encourage Patreon use, AltStore will take <strong>no commission</strong> on Patreon donations, allowing developers to keep the entirety of their Patreon proceeds.</p>

<p>Besides being a new way to monetize apps, it also gives developers a direct, personal relationship with their users. Patreon was built for creators to connect with their audience in ways that just haven’t been possible on the App Store, such as providing access to private Discords or offering exclusive content. Now app developers can leverage this too — plus you can even issue refunds, what a concept!</p>

<p>Of course, there’s another reason why we encourage developers to distribute their apps with Patreon: it allows them to cover Apple’s €0.50-per-user <a href="https://developer.apple.com/support/core-technology-fee/">Core Technology Fee</a>.</p>

<p><img title="Clip's store page" src="../../../../../assets/images/posts/altstore/clip_patreon.png" width="50%" />
<br />
<em>You can set a specific pledge amount for Patreon apps, or optionally let users choose their own pledges.</em></p>

<h2 id="about-that-core-technology-fee">About that Core Technology Fee…</h2>

<p>While Apple does waive the CTF for the first million installs of an app, <strong>this does not apply to app marketplaces themselves</strong>. This means <em>every</em> download of AltStore costs us €0.50, period. This is clearly unsustainable for a free app supported entirely by donations — especially considering we <em>already have</em> millions of users — and we’ve seen a lot of discussion hypothesizing how we could possibly afford this.</p>

<p>To us though, the answer is obvious…we can’t! So instead, we’re going to <strong>charge €1.50/year for AltStore PAL</strong> and pass the CTF onto our users.</p>

<p>We’ve done the math — a <em>lot</em> of math — and €1.50 is just enough to cover the CTF (+ payment processing) for our apps. This obviously isn’t ideal, but our priority is making sure we run AltStore sustainably so that developers can confidently distribute their apps with us — and this ensures we can pay Apple’s CTF no matter how many users we get.</p>

<p>If you’d rather not pay though — or if you‘re unlucky enough to live outside the EU — don’t worry: the existing version of AltStore isn’t going anywhere and will remain entirely free to use! Of course, that version has more limitations than AltStore PAL due to how it works (such as requiring a computer to sideload apps, and having to refresh them every 7 days), so it’s up to you whether that’s worth it.</p>

<h2 id="seriouslywhy-are-you-doing-all-this-do-you-really-love-emulators-that-much">Seriously…why are you doing all this? Do you really love emulators that much?</h2>

<p>Look, I just <a href="https://rileytestut.com/blog/2024/02/19/happy-10-birthday-gba4ios/">wrote a whole blog post</a> trying to answer this very question, so I recommend giving that a read.</p>

<p>But, this is about much more than emulators. This is about all the indie developers who’ve ever received a phone call telling them their app is rejected, but not telling them how to fix it; all the high schoolers who couldn’t release their app because it “wasn’t good enough”; all the startups who missed their launch dates due to Apple requesting yet another resubmission; all the users who think tech is boring now (it is) and assumes that’s just how it has to be (it doesn’t).</p>

<p>Honestly, Shane and I are <em>heavily</em> inspired by the <a href="https://www.youtube.com/watch?v=jX9hbbA-WP4">Super Smash Bros. Melee community</a>. They’re some of the most die-hard Nintendo fans you can imagine, yet Nintendo does almost everything in their power to push them away. They keep fighting to play this 20-year-old game no matter how many times Nintendo <a href="https://www.ign.com/articles/nintendo-shocks-competitive-fans-with-strict-new-community-tournament-guidelines">tries to stop them</a>, all because they (rightfully) think it’s just that cool. Nintendo has clearly forgotten how much fans like that matter.</p>

<p>I view Apple and Nintendo as very similar, and just like Nintendo, I think Apple has forgotten about their biggest fans: indie developers. This is incredibly disheartening, because Apple has one of the most vibrant and talented developer communities on the planet. My hope is that AltStore can pressure Apple into caring about indies more simply by being the best indie app marketplace it can be — because if there’s one thing the Smash community has taught me, it’s that the only way to change the rules is to keep playing the game :)</p>

<div style="transform:translateX(10%);">
<iframe src="https://clips.twitch.tv/embed?clip=FunSpineyReindeerBCouch-kg8VY0ji-rG0DpzB&amp;parent=rileytestut.com" frameborder="0" allowfullscreen="true" scrolling="no" height="378" width="80%"></iframe>
</div>

<p><br />
<br /></p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="altstore" /><summary type="html"><![CDATA[This is a day I’ve been looking forward to for over 10 years.]]></summary></entry><entry><title type="html">Happy 10th Birthday GBA4iOS!</title><link href="http://rileytestut.com/blog/2024/02/19/happy-10-birthday-gba4ios/" rel="alternate" type="text/html" title="Happy 10th Birthday GBA4iOS!" /><published>2024-02-19T00:00:00+00:00</published><updated>2024-02-19T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2024/02/19/happy-10-birthday-gba4ios</id><content type="html" xml:base="http://rileytestut.com/blog/2024/02/19/happy-10-birthday-gba4ios/"><![CDATA[<p>10 years ago today, I released GBA4iOS — a passion project my friend <a href="https://twitter.com/pau1thor">Paul Thorsen</a> and I built during our senior year of high school. I’ve reflected many times over the impact GBA4iOS had on my life (<a href="http://rileytestut.com/blog/2013/08/06/the-biggest-beta-test-in-ios-history/">many</a>, <a href="http://rileytestut.com/blog/2014/10/08/gba4ios-is-dead-long-live-gba4ios/">many</a>, <a href="http://rileytestut.com/blog/2020/10/14/thoughts-on-app-store/">times</a>), but for the 10th anniversary I wanted to try something different.</p>

<p>The number one question I’ve been asked, by far, over the past decade is: “why don’t you just build an app that’s allowed in the App Store?”. I’ve tried to answer this many different ways…but honestly, you just had to be there. So today I’m going to try and <em>literally</em> put you in my shoes, so you can experience first-hand why I became so obsessed with this idea.</p>

<h2 style="text-align: center;">2011</h2>

<p>You‘re a sophomore in high school. The iPhone 4s is bringing AI mainstream with its “Siri” assistant, and while it wasn’t uncommon to see students with iPhones, the majority were still rocking flip phones.</p>

<p>You’ve been developing an iPhone camera app for the past year, and you can’t help but dream someday it’ll be a huge success. Then one day your friend comes to school and shows everyone his jailbroken iPhone — and the best part about it was that it could play <em>Pokemon</em> 🤯</p>

<p>You’re incredibly jealous; Pokemon is your favorite game series of all time! Yet despite also having an iPhone, you don’t want to jailbreak. So what do you do? You put <a href="https://x.com/rileytestut/status/1534296072947806208">Pokemon Red on your TI-84 calculator</a> of course! And it <em>almost</em> scratches the itch…but there’s something about playing Pokemon on a calculator that breaks the illusion.</p>

<p>So you keep waiting.</p>

<h2 style="text-align: center;">2012</h2>

<p>You’re a junior now, and the iPhone 5 is all the rage with its giant new 4” display. You’re browsing GitHub for interesting open source iOS projects when one catches your eye: “gpSPhone — Game Boy Advance emulator for jailbroken iPhones.” You can’t believe it, this is the <em>exact</em> emulator your friend was using!</p>

<p>You wonder if it’d be possible to modify the project to run on non-jailbroken devices, but to your dismay Xcode reports “999+“ compiler errors and you almost give up then. However, the determination to replay your favorite Pokemon game — Pokemon Emerald — is too strong, so you take a deep breath and chug away. Just a couple months later you have your breakthrough — you successfully emulate Pokemon Emerald on a non-jailbroken iPhone for the first time 🥳</p>

<p>You quickly clean up the codebase, and the next day you excitedly bring your laptop to school so you can install your Frankenstein app onto your friends’ phones. Soon your whole friend group is playing Pokemon, and you even start battling each other during lunch! You decide since it’s a hit with your friends, you might as well upload the code to GitHub for other developers to play with. So you give the app a proper name — GBA4iOS, inspired by other iPhone emulators like “snes4iphone” — and upload the project to a new repo.</p>

<p>Then you go back to playing Pokemon with your friends.</p>

<h2 style="text-align: center;">2013</h2>

<p>It’s the summer before senior year. Apple has just announced a completely redesigned iOS 7, and “skeuomorphism” is quickly becoming a dirty word.</p>

<p>Seemingly out of nowhere, your Twitter grows from around 200 followers to more than 1000 a week later, and your mentions become flooded with questions about emulating Game Boy games. Apparently, someone had <a href="https://try.macbuildserver.com">made a tool</a> to install open-source iOS apps by signing them with an “enterprise certificate”, and people were using this tool to “sideload” GBA4iOS. Even wilder, this process worked <em>even if the enterprise certificate was expired</em>, as long as you set your date back at least 24 hours (a process that became known as the “date trick”).</p>

<p>You immediately realize the potential — for the first time ever there seemed to be a way to distribute emulators on iOS without jailbreaking! So you decide to rewrite GBA4iOS from the ground-up and make it a truly polished experience. You mention these thoughts to your best friend Paul, and he wants to be a part of it too. His design skills are much better than yours, so he tells you bluntly your app is ugly and that you need him. You can’t disagree with him, so you bring him on and and you both get to work building “GBA4iOS 2.0”.</p>

<p>You make good progress that summer, and once senior year starts you continue to spend almost all your free time working together. You don’t know how long it will take, but the dream of “officially” releasing an emulator for iPhone is all you need to stay motivated.</p>

<h2 style="text-align: center;">2014</h2>

<h3 style="text-align: center;">February 19 — Launch Day</h3>

<p>You’re now a senior, and biometric security is the hot new thing thanks to the iPhone 5s and “Touch ID.” By now, the majority of students are “blue bubbles”; fueled <em>heavily</em> by Apple introducing iMessage a few years prior.</p>

<p>You arrive at school at 9am like normal, except today you’re wearing your custom-made GBA4iOS T-shirt. 5 days earlier you had updated the GBA4iOS website with a countdown, and it’s set to finish today at 2:45pm CST — coinciding with the film class period you and Paul share (and also where a significant amount of GBA4iOS development took place). You’d somehow managed to convince your film teacher to let you throw a launch party that day to celebrate…as long as you filmed it and made a short documentary about GBA4iOS for your next class project (<a href="https://www.youtube.com/watch?v=BtWjjbei-vE">which you did</a>).</p>

<p>The day goes by incredibly slowly, and you can barely focus on class. When the bell finally rings for film period, you put the GBA4iOS website + countdown on the projector and hand out pizzas you’d ordered to the classroom’s backdoor. With just a few minutes left, you upload the final GBA4iOS build to the server, then stand back and finally soak in what’s happening. Almost 9 months of hard work had let to this moment, and you can barely contain your nervousness.</p>

<p>30 seconds left, you remember your promise and pull out your iPhone 5s to film the final moments. At this point, there’s only one thought in your head: <em>will this actually work?</em></p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/2Coa9RDPfvs?si=MVfZ4mzkvQndOOu7" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>

<p>Spoiler alert: it does — against all odds you successfully release a Game Boy Advance emulator for iPhone!</p>

<h3 style="text-align: center;">October 7 — My Birthday</h3>

<p>You’ve graduated high school, and the iPhone 6 Plus is blowing everyone’s minds with how big it is. You’re taking a semester off before college, which conveniently gives you time to focus on developing GBA4iOS. The past several months are a blur, but the response to GBA4iOS has been far better than you could have ever imagined; they even wrote about you in <a href="https://techland.time.com/2014/02/25/ios-has-a-jailbreak-free-game-boy-emulator-and-its-better-than-ever/">Time Magazine</a>!</p>

<p>You’re hard at work on version 2.1 when you see a headline you’ve been dreading since launching GBA4iOS 8 months prior: <a href="https://www.cultofmac.com/298945/apple-blocks-date-trick-loophole-allows-emulators-ios/">“iOS 8.1 blocks ‘date trick’ loophole that allows emulators on iPhone and iPad“</a>. You’re not surprised…but it’s hard to contain the disappointment you feel. For a brief, glorious, few months, you had experienced what it was like to make an app that was used by millions — despite it being one that by all accounts “shouldn’t exist”. You knew you were living on borrowed time, but it just felt <em>wrong</em> that an app this popular can never exist on iOS.</p>

<p>But it’s not like you can do anything about it. You’re just one person, and you’re about to enter college anyway, so you decide it’s time to move on. You <a href="http://rileytestut.com/blog/2014/10/08/gba4ios-is-dead-long-live-gba4ios/">announce GBA4iOS is officially dead</a>, then prepare to go to college.</p>

<h2 style="text-align: center;">2015</h2>

<p>You‘re a freshman in college, and you‘re <em>really</em> feeling the itch to have a passion project again. Apple just announced a brand new programming language called Swift, and you figure you might as well start learning it now before you get left behind in Objective-C land.</p>

<p>You try to think of a new idea that excites you, and since this is just for fun, you decide to push yourself and make an <em>all-in-one</em> Nintendo emulator — entirely written in Swift — because why not? You sit down, and the first thing Xcode asks is for a name. You pause for a moment, then to your surprise come up with a name faster than any app you’ve made before: <em>Delta</em>.</p>

<p>A few months later you attend your first ever WWDC. You sign up for everything to ensure you make the most of it — including the App Review lab, because what’s the harm in asking about Delta? And you‘re very glad you did, because to your amazement they tell you Delta actually <em>could</em> be approved as long as you were willing to jump through some minor hurdles (such as providing “allowlist” of approved games). You enthusiastically agree to whatever hurdles, because you’ll do anything to distribute Delta through the App Store.</p>

<p>Almost 3 years after starting work on GBA4iOS, your dream was <em>finally</em> coming true: 2015 was going to be the year you officially release an emulator for iPhone 🙏</p>

<h3 style="text-align: center;">…</h3>
<h2 style="text-align: center;">2024</h2>

<p>You’re self-employed and still making apps, and your 10 year high school reunion is coming up. There isn’t too much new with iPhones anymore, but at least lightning is finally gone and replaced with USB-C!</p>

<p>It’s been 10 years since you released GBA4iOS, and almost 15 since you started down this rabbit hole. The European Union has recently passed legislation that will force Apple to allow alternative “app marketplaces”, all but guaranteeing a pathway to distribute Delta. You don’t want to jinx yourself because you’ve been burned many times before, but you can’t help but feel that this year is finally, <em>actually</em>, the year you’ve been waiting over a decade for:</p>

<p>This is the year emulators come to iPhone.</p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="gba4ios" /><summary type="html"><![CDATA[10 years ago today, I released GBA4iOS — a passion project my friend Paul Thorsen and I built during our senior year of high school. I’ve reflected many times over the impact GBA4iOS had on my life (many, many, times), but for the 10th anniversary I wanted to try something different.]]></summary></entry><entry><title type="html">Delta 1.3 - Nintendo DS Emulation For Everyone</title><link href="http://rileytestut.com/blog/2021/04/21/delta-1-3-ds-for-everyone/" rel="alternate" type="text/html" title="Delta 1.3 - Nintendo DS Emulation For Everyone" /><published>2021-04-21T00:00:00+00:00</published><updated>2021-04-21T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2021/04/21/delta-1-3-ds-for-everyone</id><content type="html" xml:base="http://rileytestut.com/blog/2021/04/21/delta-1-3-ds-for-everyone/"><![CDATA[<p>After more than a year in development, I’m thrilled to announce Delta 1.3 is now available and brings support for playing Nintendo DS games to everyone 🥳</p>

<h2 id="delta-meet-ds">Delta, meet DS</h2>
<p>When I first <a href="https://rileytestut.com/blog/2019/09/25/introducing-altstore/">launched Delta almost 2 years ago</a>, I announced that support for playing DS games would be coming soon, and released a beta version of Delta exclusively for <a href="https://www.patreon.com/rileytestut">my Patrons</a> that included an early preview of the feature. Unsurprisingly, this initial release was extremely buggy — but thanks to feedback from my Patrons, I’ve continued to refine Delta’s DS support over time, and now it’s finally stable enough for public use!</p>

<h4 id="powered-by-melonds">Powered by melonDS</h4>
<p>Delta originally used <a href="http://desmume.org">DeSmuME</a> to emulate DS games, but after some discussions with my Patrons I decided to instead switch to <a href="http://melonds.kuribo64.net">melonDS</a>. This switch was motivated by the fact that DeSmuME development has mostly stalled while melonDS is still being actively developed, as well as melonDS supporting features I would eventually like to add to Delta that DeSmuME doesn’t (such as multiplayer support).</p>

<p>However, there were still some features I wanted to add that weren’t already supported by melonDS, so I ended up <a href="https://github.com/rileytestut/melonDS">forking melonDS</a> to implement them. Specifically, my changes were:</p>

<ul>
  <li>Added callback function for when melonDS requests microphone data, allowing Delta to delay activating the microphone until it is actually needed.
    <ul>
      <li><a href="https://github.com/rileytestut/melonDS/commit/398b8bb5b2b09be9f67363c9934dbcadf67aa6cf"><code class="language-plaintext highlighter-rouge">Add Mic_Prepare() callback (398b8bb)</code></a></li>
    </ul>
  </li>
  <li>Supports JIT on iOS by mapping separate virtual memory addresses with different permissions (one with EXEC permissions, the other with READ and WRITE) to the same underlying memory.
    <ul>
      <li><a href="https://github.com/rileytestut/melonDS/commit/1d27e4cf8a88a0642b3f03732036996f7d27e365"><code class="language-plaintext highlighter-rouge">Support JIT on Apple platforms (1d27e4c)</code></a></li>
      <li><a href="https://github.com/rileytestut/melonDS/commit/c353e7760be6a61f6dc34551d5b10637aafaa04b"><code class="language-plaintext highlighter-rouge">Fix crash on Apple devices without JIT support (c353e77)</code></a></li>
      <li><a href="https://github.com/rileytestut/melonDS/commit/e40bc378f8d7aee953eb65e54d25cffe21f92aea"><code class="language-plaintext highlighter-rouge">Fix fastmem crash on Apple devices with small VM address space (e40bc37)</code></a></li>
    </ul>
  </li>
  <li>Skips rendering frames that will not be displayed due to fast forwarding for improved performance.
    <ul>
      <li><a href="https://github.com/rileytestut/melonDS/commit/a87e0d95c42b2dc832978ab1178feaa3a286a672"><code class="language-plaintext highlighter-rouge">Add NDS::SkipFrame to skip rendering next frame (a87e0d9)</code></a></li>
    </ul>
  </li>
</ul>

<p>Unlike DeSmuME, melonDS requires several “BIOS” files in order to work, which can be found &amp; downloaded relatively easily by Googling (no, I can’t link you to them sorry). Once you’ve imported these files in Delta’s Nintendo DS core settings, you’ll then be able to emulate DS games as normal, and even access the DS home screen to change settings such as your nickname, theme color, etc.</p>

<p>⚠️ For now, DeSmuME will remain an optional core in beta versions of Delta. This allows Patrons to keep using any DeSmuME save states they’ve already made, and eventually migrate to melonDS. However, all future DS improvements will be limited to the melonDS core, and eventually DeSmuME will be permanently removed.</p>

<h4 id="beautiful-controller-skin">Beautiful Controller Skin</h4>
<p>Every Delta system comes with its own custom-designed controller skin optimized for touch, and DS is no different! Like Delta’s other controller skins, this skin was designed by <a href="https://twitter.com/1carolinemoore">Caroline Moore</a> and pays homage to the original DS hardware — in this case, the iconic pink Nintendo DS Lite.</p>

<div style="transform:translateX(-16%);">
<img title="Portrait DS Controller Skin" src="../../../../../assets/images/posts/delta/ds/ds_skin_portrait.png" width="30%" style="transform:translateX(-100%);" />
<img title="Landscape DS Controller Skin" src="../../../../../assets/images/posts/delta/ds/ds_skin_landscape.png" width="60%" /><br />
</div>
<p><em>The standard DS controller skin adapts perfectly to both portrait and landscape orientations.</em></p>

<h4 id="jit-compilation">JIT Compilation</h4>
<p>melonDS can run at 100% speed on most newer iOS devices, but Delta can only fast forward up to 1.5x for a few minutes before being throttled by the system. By enabling just-in-time (JIT) compilation, however, Delta can dramatically improve melonDS performance — doubling the maximum fast forward speed from 1.5x to 3x. Even with this speed increase, the overall boost in performance is enough to also prevent iOS from throttling your device’s CPU after fast forwarding for extended periods, allowing you to play games at 3x speed without <em>any</em> slowing down.</p>

<p>Unfortunately, there is one major caveat: Delta’s current JIT implementation only works on iOS 14.2 — 14.3. This is because only these iOS versions allow JIT without any restrictions (for whatever reason), which unfortunately was changed in iOS 14.4. In other words, <strong>melonDS JIT is not supported on devices running iOS 14.4 or later.</strong></p>

<p>That being said, there is hope! I’ve discovered a new method to enable JIT on devices running iOS 14 or later — including iOS 14.4 and the upcoming iOS 14.5 — which I plan to release in beta soon. This new method is slightly more complex than what iOS 14.2 and 14.3 support, but I plan to automate as much complexity as possible so it can “just work” — so stay tuned 😉</p>

<h4 id="microphone-support">Microphone Support</h4>
<p>A small but nice feature: Delta can use your iOS device’s microphone to emulate the DS’ microphone. Probably not a feature you’ll need often, but when you <em>do</em> come across a game that requires the microphone, Delta has you covered 💪</p>

<p><img title="Using microphone with Mario Party DS" src="../../../../../assets/images/posts/delta/ds/mario_party_mic.png" width="60%" /><br />
<em>Mario Party DS makes extensive use of the DS microphone.</em></p>

<h4 id="simulate-closing--opening-ds-lid">Simulate Closing &amp; Opening DS Lid</h4>
<p>Even more niche than microphone support, Delta can simulate closing &amp; opening the DS lid just by sleeping &amp; waking your device. For the vast majority of games this doesn’t matter — but at least now you can hear Mario saying “Bye-Bye!” when playing New Super Mario Bros. 🤷‍♂️</p>

<h4 id="misc-ds-features">Misc. DS Features</h4>
<p>Of course, DS games support all the same features you’re used to with Delta’s other consoles, including:</p>
<ul>
  <li>Save States</li>
  <li>Cheats (Action Replay)</li>
  <li>Fast Forwarding (up to 3x with JIT, 1.5x without)</li>
  <li>Game Controller support</li>
</ul>

<p>Delta strives to be the best emulator for each system it supports, so keep in mind these are just the initial DS features! I plan to add several more features — such as local and online multiplayer — in the future, and would love to hear what features y’all want most 😄</p>

<h2 id="other-delta-13-changes">Other Delta 1.3 Changes</h2>
<p>Besides DS support, Delta 1.3 also comes with a <em>bunch</em> of additional features and changes to improve the overall experience using the app.</p>

<h4 id="dark-mode-support">Dark Mode Support</h4>
<p>Thanks to <a href="https://github.com/rileytestut/Delta/pull/82">Eric Lewis</a>, Delta now supports Dark Mode throughout the app! Delta already used a dark theme for its main UI, but several secondary screens such as Settings used a lighter theme — which could be especially jarring to switch between in dark environments. Now these secondary screens will also take on a dark appearance when your device is in Dark Mode, saving you from burning your eyes at night!</p>

<div style="transform:translateX(-16%);">
<img title="Settings in Dark Mode" src="../../../../../assets/images/posts/delta/settings_dark.png" width="33%" style="padding-right:10px;" />
<img title="Entering Cheat in Dark Mode" src="../../../../../assets/images/posts/delta/cheats_dark.png" width="33%" />
</div>
<p><em>All screens now support dark mode, including Delta’s settings and the “Add Cheat” screen.</em></p>

<h4 id="audio-distortion-fix">Audio Distortion Fix</h4>
<p>When playing games for an extended period of time, Delta would randomly start distorting the game audio for several minutes before (hopefully) fixing itself. I spent several days trying to track down the cause, and eventually hypothesized the issue had something to do with Delta’s audio “ring buffer” becoming corrupted. Unfortunately, as a visual problem solver it was hard for me to “visualize” how exactly the ring buffer was corrupted whenever I reproduced it (did it fill up too quickly? did it not fill up quickly enough?), but then it hit me: I could graph the memory addresses of the audio buffer’s head and tail pointers, and then I could visually see whether anything strange was going on!</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">today I fixed an audio bug by plotting memory addresses in Numbers AMA <a href="https://t.co/TfA9qjpcD1">pic.twitter.com/TfA9qjpcD1</a></p>&mdash; Riles 🤷‍♂️ (@rileytestut) <a href="https://twitter.com/rileytestut/status/1333607308765650945?ref_src=twsrc%5Etfw">December 1, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>Sure enough, I noticed that occasionally the ring buffer’s head pointer would go “beyond” the tail pointer, effectively corrupting the audio data. But why? Simple: good ol’ human error 🙃 I originally used <a href="https://github.com/michaeltyson/TPCircularBuffer">TPCircularBuffer</a> as-is for Delta’s audio buffer, but in order to launch <a href="https://github.com/rileytestut/DeltaLite">Delta Lite</a> I needed to rewrite everything in Swift so that it could be used from Swift Playgrounds. So, I re-wrote TPCircularBuffer line-for-line in Swift, and then continued working on Delta Lite without giving it another thought…but as it turns out, this rewrite was what caused the bug in the first place.</p>

<p>I checked my code to see why the head pointer would go beyond the tail, but didn’t see anything obvious (I already had bounds-checking logic that should’ve prevented something like this), so I wondered if there was some strange concurrency issue at play. I decided to check out TPCircularBuffer’s source again to see if there was anything I missed, and to my delight the README had an explicit “Thread safety” section which mentioned:</p>

<blockquote>
  <p>As long as you restrict multithreaded access to just one producer, and just one consumer, this utility should be thread safe.</p>

  <p>Only one shared variable is used (the buffer fill count), and OSAtomic primitives are used to write to this value to ensure atomicity.</p>
</blockquote>

<p>BINGO! In my re-implementation, I did <em>not</em> use OSAtomic primitives when updating the buffer fill count, because I (naively) assumed it was unnecessary at the time 😅 Sure enough, once I updated Delta’s RingBuffer to <a href="https://github.com/rileytestut/DeltaCore/commit/3ad5f97b33a3e18983da0ea932fdcfe63fe387dc">atomically update the buffer fill count via OSAtomic primitives</a>, the issue disappeared once and for all!</p>

<h4 id="better-real-time-clock-support">Better Real Time Clock Support</h4>
<p>Another long requested bug fix, Delta 1.3 now supports the Real Time Clock (RTC) for <em>all</em> Game Boy Advance games — including Pokémon hacks. Previously Delta would only enable RTC if it detected the game needed it, but this detection was imperfect and led to several false negatives. Now, RTC is enabled for all games by default, so any game that didn’t work with Delta’s RTC before should now work as expected.</p>

<h4 id="quality-of-life-improvements">Quality-Of-Life Improvements</h4>
<p>Besides these bigger changes, Delta 1.3 also contains several quality-of-life improvements, including:</p>

<ul>
  <li>Option to disable previews when using context menu</li>
  <li>Support for transparency in game artwork</li>
  <li>“Import Controller Skin” button when changing controller skins</li>
</ul>

<h2 id="future-roadmap">Future Roadmap</h2>
<p>Now that Delta 1.3 is finished, it’s time to start working on Delta 2.0! Delta 2.0 will be the biggest update yet to Delta, adding support for iPad and macOS as well as a bunch of other awesome features. What awesome features exactly though? Well…that’s up to you!</p>

<p>To make it easier to stay up-to-date with the latest Delta developments, there is now an official <a href="https://trello.com/b/P6YH3nl9/delta-emulator-roadmap">Delta Emulator Roadmap Trello board</a>. In addition to listing all the features I either plan to add or that are already in development, this board also lets you <em>vote</em> on which features you’re most interested in, helping me prioritize what features to work on next. I’ve been testing it internally with my Patrons for the past few months and it’s been a huge help, so if you’d like to have a say in what features make it into Delta 2.0, <em>please</em> check it out — with your feedback, we can continue to make Delta the best possible app it can be 🙏</p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="delta" /><category term="ds" /><summary type="html"><![CDATA[After more than a year in development, I’m thrilled to announce Delta 1.3 is now available and brings support for playing Nintendo DS games to everyone 🥳]]></summary></entry><entry><title type="html">Thoughts on the App Store</title><link href="http://rileytestut.com/blog/2020/10/14/thoughts-on-app-store/" rel="alternate" type="text/html" title="Thoughts on the App Store" /><published>2020-10-14T00:00:00+00:00</published><updated>2020-10-14T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2020/10/14/thoughts-on-app-store</id><content type="html" xml:base="http://rileytestut.com/blog/2020/10/14/thoughts-on-app-store/"><![CDATA[<p>One year ago, <a href="http://rileytestut.com/blog/2019/09/25/introducing-altstore/">I launched AltStore</a> as a brand new way to sideload apps not allowed in the App Store, including my Nintendo emulator Delta. Since then, the conversation regarding sideloading and Apple’s control over the App Store has grown <em>tremendously</em>. In just the past year:</p>

<ul>
  <li><a href="https://www.theverge.com/2019/10/10/20907596/apple-hong-kong-protests-app-removed-china">Apple removes app used in Hong Kong protests after pressure from China</a></li>
  <li><a href="https://www.theverge.com/2020/6/16/21292651/apple-eu-antitrust-investigation-app-store-apple-pay">EU opens Apple antitrust investigations into App Store and Apple Pay practices</a></li>
  <li><a href="https://www.theverge.com/2020/6/18/21296180/apple-hey-email-app-basecamp-rejection-response-controversy-antitrust-regulation">Apple doubles down on controversial decision to reject email app Hey</a></li>
  <li><a href="https://www.imore.com/tim-cook-defends-apple-and-its-app-store-us-house-antitrust-hearing">Tim Cook defends Apple and its App Store at U.S. House antitrust hearing</a></li>
  <li><a href="https://www.nytimes.com/2020/08/13/technology/apple-fortnite-ban.html">Fortnite Creator Sues Apple and Google After Ban From App Stores</a></li>
  <li><a href="https://www.cnet.com/news/xbox-slams-apple-for-blocking-microsofts-project-xcloud-streaming-game-service/">Xbox slams Apple for blocking Microsoft’s Project xCloud streaming game service</a></li>
  <li><a href="https://www.theverge.com/2020/8/21/21396316/apple-wordpress-in-app-purchase-tax-update-store">WordPress founder claims Apple cut off updates to his completely free app because it wants 30 percent</a></li>
</ul>

<p>Capping things off, just last week the U.S. House <a href="https://www.theverge.com/2020/10/6/21504814/congress-antitrust-report-house-judiciary-committee-apple-google-amazon-facebook">released their highly anticipated tech antitrust report</a>, in which they explicitly stated that Apple’s monopolistic power in the mobile app store market has caused real harm to developers and end users.</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">According to congress, Apple “exerts monopoly power in the mobile app store market,” which “has resulted in harms to competitors and competition, reducing quality and innovation among app developers, and increasing prices &amp; reducing choices for consumers.” <a href="https://t.co/SR7H51LCuP">https://t.co/SR7H51LCuP</a> <a href="https://t.co/CBrTjEoMLN">pic.twitter.com/CBrTjEoMLN</a></p>&mdash; Riles 🦄 (@rileytestut) <a href="https://twitter.com/rileytestut/status/1313590087473459200?ref_src=twsrc%5Etfw">October 6, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>I’ve been wanting to write up my thoughts on the App Store for a while, but had trouble solidifying <em>exactly</em> how I felt about it. As a user, I love the App Store and would hate to see it become less important to iOS. In practice though, the current App Store situation has some significant problems which are getting harder and harder to ignore — several of which Congress’ antitrust report explicitly call out, such as requiring developers to implement in-app purchases or risk being thrown out of the App Store. I’ve wrestled with these two seemingly conflicting notions for a long time, but after running an alternative app store for the past year I’ve finally been able solidify my thoughts on what I believe is best for the platform.</p>

<p>So to celebrate AltStore’s first birthday, I decided to finally write up my thoughts on the App Store — including why I went through all this effort in the first place and why I believe sideloading is ultimately the right long-term solution for iOS. I know my opinions won’t be shared by everyone, but hopefully my perspective will at least shine some light on the real value sideloading adds <em>today</em> to the platform, not just in a hypothetical future.</p>

<h2 id="my-app-store-y-from-gba4ios-to-delta">My App Store-y: From GBA4iOS to Delta</h2>

<p>Back in 2013 while still in high school, I built a Game Boy Advance emulator app for fun that let me play Pokémon Emerald (and every other GBA game) on my phone. It was nothing spectacular, but it worked, so once I installed it on a few of my friends’ phones I decided to upload the source code to GitHub under the name “GBA4iOS”.</p>

<p>I soon <a href="http://blog.macbuildserver.com/2013/05/07/test-github-ios-projects-right-on-your-device/">discovered a service</a> that allowed anyone to install open source iOS apps over-the-air (OTA) by signing them with an enterprise certificate, so on a whim I decided to promote that as the “official” way to install GBA4iOS. Long story short: GBA4iOS blew up, and I accidentally found myself working full-time on an app not available in the App Store. Unfortunately, Apple eventually <a href="http://blog.macbuildserver.com/2013/07/17/ooh-ahhh-apple-befell-on-us/">revoked the enterprise certificate</a> I was using to distribute it (and <a href="http://rileytestut.com/blog/2014/10/08/gba4ios-is-dead-long-live-gba4ios/">patched the subsequent “Date Trick”</a> that allowed it to keep working by setting your iPhone’s date back), ending my brief but exciting time working on GBA4iOS.</p>

<p>Following GBA4iOS’ success (and untimely death), I then got to work on my next project: Delta, an all-in-one Nintendo emulator. Rather than devote all my time to building another app that wouldn’t be allowed in the App Store, I decided to reach out to Apple directly and work with them to find a way to get Delta approved. To my delight, I was told by the App Review team that Delta could be approved as long as I provided Apple with an allowlist of games they could review and deem “acceptable” for users (<a href="https://toucharcade.com/2020/08/06/apples-statement-regarding-xcloud-on-ios/">sound familiar?</a>). Willing to do <em>anything</em> to get Delta in the App Store, I accepted the restrictions and got back to work.</p>

<p>One year later I’d made significant progress with Delta, so I reached out again to Apple to discuss actually submitting Delta to the App Store. Unfortunately…that’s when Apple told me Delta would not be allowed in the App Store after all because they “can’t allow emulators”. I was stunned; Apple had led me on for a year, then when it came time to follow through they changed their minds and told me emulators were not allowed in the App Store, period. Just like that, all the work I had put into Delta was for nothing. Because the App Store was the only way to distribute apps at scale to iPhone users, I had no choice but to accept Apple’s decision and throw away all my work.</p>

<p>Except, I didn’t. The <em>only</em> thing I cared about was getting Delta into the hands of anyone who wanted it, and there was no way I was going to give up just like that. If Apple wasn’t going to give me a way to do that, so be it — I’d just have to build it myself.</p>

<h2 id="sideloading-a-sweet-solution">Sideloading: A Sweet Solution</h2>

<p>Contrary to popular belief, iOS <em>does</em> actually support sideloading apps not in the App Store. Starting with iOS 9, Apple allows anyone with an Apple ID to use Xcode and install apps they’ve developed themselves to their devices — even without a paid developer account. Apple made this change to better accommodate students who couldn’t afford Apple’s $99/year developer fee, because they realized how important it was to be able to run your own code on your device.</p>

<p>How then does Apple’s own approved sideloading solution work? On a technical level, it’s the same as with a paid developer account: Xcode “signs” a compiled app (.ipa) with a certificate and provisioning profile associated with your Apple ID, which allows it to be installed and pass code-signing checks on any device whose UDID is included in the provisioning profile. However, Apple also added several limitations for apps signed by non-developer accounts, in what I assume are attempts to make this too cumbersome for mainstream adoption. Here’s a comparison between the two:</p>

<p><strong>Paid Developer Account</strong></p>
<ul>
  <li>Apps expire after 365 days</li>
  <li>No limit to number of apps you can sideload</li>
  <li>No limit to number of “App IDs” you can register with Apple (one App ID is required for each sideloaded app <em>and</em> app extension)</li>
  <li>Can be installed via computer or OTA</li>
</ul>

<p><strong>Regular Apple ID</strong></p>
<ul>
  <li>Apps expire after 7 days</li>
  <li>Limited to 3 sideloaded apps installed at a time</li>
  <li>Limited to registering up to 10 App IDs every 7 days, but no more than 10 App IDs can be registered at any time</li>
  <li>Cannot be installed without a computer</li>
</ul>

<p>Even with restrictions, having a way to sideload apps is way better than none at all. Yet despite <a href="https://9to5mac.com/2015/06/10/xcode-7-allows-anyone-to-download-build-and-sideload-ios-apps-for-free/">some initial excitement</a>, in practice the restrictions proved too strict for day-to-day app usage. Apple finally built a legitimate way to sideload apps, but (by design) no one was using it due to how cumbersome it was.</p>

<p>Wouldn’t it be great if there was a way to make this process just a <em>tad</em> bit easier, for those who really wanted it and were willing to go through the effort?</p>

<h2 id="altstore">AltStore</h2>

<p>From working on GBA4iOS, I knew there was a demand for apps that weren’t allowed in the App Store. So rather than build out a whole distribution method just for Delta, why not build it in a way so that it can be used by other developers as well? That was the crux of AltStore’s philosophy: build a home for apps that really push the boundaries of what iOS can do, and make them available for everyone.</p>

<p>I wanted to build a method that couldn’t easily be stopped by Apple, which is why I decided to base it on the existing Xcode sideloading support. By providing your Apple ID and password, AltStore can sign in with your Apple ID and “resign” apps so they can be installed to your device. Since iOS devices can’t sideload apps directly, AltStore sends resigned apps to AltServer — a desktop companion app for Mac/PC — which then installs the apps back to your device via iTunes WiFi Sync.</p>

<p>Would this really be worth it though? Would people really download a desktop app to download an iOS app to download Delta, especially when it involves trusting a stranger with their Apple ID and password? Do people really want sideloading <em>that</em> bad?</p>

<p>As it turns out: absolutely!</p>

<p>One year later, I couldn’t be happier with the response: AltStore has been downloaded by over 1 million people to sideload over 100 different apps to their iOS devices, and it’s still growing every day! It’s been absolutely incredible to see what ideas are possible without the constraints of App Review; in a way, it feels like a return to the early days of the App Store where creativity and indie developers flourished, rather than the more corporate marketplace it is today.</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">One year ago we launched AltStore as a safe way to install apps outside the App Store, including our Nintendo emulator Delta. We never could’ve anticipated the amazing response — over 1 million people have sideloaded 100+ different apps — and we’re only just getting started 🥳 <a href="https://t.co/YnIxYUeVI4">pic.twitter.com/YnIxYUeVI4</a></p>&mdash; AltStore.io 🦄 (@altstoreio) <a href="https://twitter.com/altstoreio/status/1310740366576893955?ref_src=twsrc%5Etfw">September 29, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>But don’t take my word for it. Here are 5 of the most popular apps available with AltStore today:</p>

<p><strong>Delta</strong><br />
My all-in-one Nintendo emulator that allows you to play any NES, SNES, GBC, GBA, N64, and DS game on your iPhone (and soon iPad + macOS). Not allowed in the App Store because Apple doesn’t allow emulators.<br />
Website: https://deltaemulator.com/<br />
GitHub: https://github.com/rileytestut/Delta</p>

<div style="transform:translateX(-16%);">
<img title="Delta Screenshot 1" src="../../../../../assets/images/posts/apps/delta1.png" width="33%" style="padding-right:10px;" />
<img title="Delta Screenshot 2" src="../../../../../assets/images/posts/apps/delta2.png" width="33%" />
</div>

<p><img title="Delta Screenshot 3" src="../../../../../assets/images/posts/apps/delta3.png" width="75%" /></p>

<p><br /></p>

<p><strong>Clip</strong><br />
My clipboard manager that can actually run in the background indefinitely and listen for changes to your clipboard to save them for later. Not allowed in the App Store because apps aren’t allowed to run forever in the background, or use private APIs (necessary for listening to clipboard changes in background).<br />
Blog Post: http://rileytestut.com/blog/2020/06/17/introducing-clip/<br />
GitHub: https://github.com/rileytestut/Clip</p>

<div style="transform:translateX(-16%);">
<img title="Clip Screenshot 1" src="../../../../../assets/images/posts/apps/clip1.png" width="33%" style="padding-right:10px;" />
<img title="Clip Screenshot 2" src="../../../../../assets/images/posts/apps/clip2.png" width="33%" />
</div>

<p><br /></p>

<p><strong>UTM</strong><br />
A complete Virtual Machine app based on QEMU that lets you run Windows, Linux, macOS, and more on your iOS device. Not allowed in the App Store because Apple doesn’t allow emulators.<br />
Website: https://getutm.app/<br />
GitHub: https://github.com/utmapp/UTM</p>

<div style="transform:translateX(-16%);">
<img title="UTM Screenshot 1" src="../../../../../assets/images/posts/apps/utm1.png" width="33%" style="padding-right:10px;" />
<img title="UTM Screenshot 2" src="../../../../../assets/images/posts/apps/utm2.png" width="33%" />
</div>

<div style="text-align: center; padding-top:10px;">
<iframe width="574" height="287" src="https://www.youtube.com/embed/LrLDKYFyLMM" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>

<p><br /></p>

<p><strong>iSH</strong><br />
A full-featured Linux shell for iOS, allowing users to run real Linux applications and programs with a native command line experience. Not allowed in the App Store because Apple doesn’t allow Terminal-like apps (…or Linux emulation).<br />
Website: https://ish.app/<br />
GitHub: https://github.com/ish-app/ish</p>

<p><img title="iSH Screenshot" src="../../../../../assets/images/posts/apps/ish1.png" width="45%" /></p>

<p><br /></p>

<p><strong>DolphiniOS</strong><br />
A port of the popular cross-platform emulator, DolphiniOS allows you to play any GameCube or Wii game on your iOS device, with advanced options like upscaling graphics to 1080p (or higher!). Not allowed in the App Store because Apple doesn’t allow emulators.<br />
Website: https://dolphinios.oatmealdome.me/<br />
GitHub: https://github.com/OatmealDome/dolphin</p>

<div style="transform:translateX(-16%);">
<img title="DolphiniOS Screenshot 1" src="../../../../../assets/images/posts/apps/dolphin1.jpeg" width="33%" style="padding-right:10px;" />
<img title="DolphiniOS Screenshot 2" src="../../../../../assets/images/posts/apps/dolphin2.png" width="33%" />
</div>

<div style="text-align: center; padding-top:10px;">
<iframe width="574" height="287" src="https://www.youtube.com/embed/Kztd8S0nzVw" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>

<p><br /></p>

<p>Far too much focus has been spent on the financial impact of Apple’s role as Gatekeeper, but the reality is that’s just one part of this whole debate. That may be what the big companies are most concerned with, but us smaller developers are far more concerned with being able to distribute our apps at all. The above apps are all products of love by their respective developers, and no change to the App Store’s payment policies will allow these apps in the App Store.</p>

<p>The <em>only</em> solution for these apps is sideloading.</p>

<h2 id="back-to-the-app-store">Back to the App Store</h2>

<p>An App Store-exclusive model worked well for iOS’ first decade or so, but as the platform matures it’s becoming more and more evident what the downsides are to such strict control. <a href="https://marco.org/2020/09/11/app-review-changes">Increasingly convoluted rules regarding payment systems</a>, <a href="https://www.theverge.com/2020/8/6/21357771/apple-cloud-gaming-microsoft-xcloud-google-stadia-ios-app-store-guidelines-violations">outright banning of new industries</a> (without <a href="https://www.theverge.com/2020/9/18/20912689/apple-cloud-gaming-streaming-xcloud-stadia-app-store-guidelines-rules">ridiculous compromises</a>), <a href="https://qz.com/1725175/apple-removed-a-hong-kong-protest-map-from-its-app-store/">censorship by authoritarian governments</a> (<a href="https://www.nytimes.com/2020/09/18/business/trump-tik-tok-wechat-ban.html">including the United States</a>), <a href="https://arstechnica.com/information-technology/2020/09/scam-apps-with-2-4-million-downloads-found-on-apple-and-google-shelves/">scam apps sneaking through review</a> (<a href="https://daringfireball.net/2020/09/widgetsmith_bunco_squad">repeatedly</a>)…you get the picture.</p>

<p>Combined with the <a href="https://www.wsj.com/articles/developers-sue-apple-over-app-store-costs-11559671769">ongoing</a> <a href="https://9to5mac.com/2020/08/13/epic-games-bornite-app-store-apple/">legal battles</a> regarding Apple’s control over the App Store, I believe the tide has finally turned.</p>

<p>12 years on, it’s clear that while band-aids can be applied to the App Store Guidelines every few years or so to quell developer dissent, the underlying philosophy that Apple maintains sole discretion over which apps are allowed to run on its platform is showing its age. Imagine a world where Apple had rejected Uber or Lyft on the basis ride-sharing was inherently unsafe. That would have been completely defensible — I personally would have most likely supported it — but without iOS the entire ride-sharing market would simply never have existed. Now imagine a world where Apple rejects all vape-related apps on the basis vaping is inherently unsafe — oh wait, that one <a href="https://www.nytimes.com/2019/11/15/business/apple-vaping-apps.html">actually happened</a>.</p>

<p>I don’t fault Apple for these decisions — I think it’s entirely reasonable for them to reject potentially unsafe apps from their store out of an abundance of caution. In fact, I’d love to see Apple <a href="https://tirania.org/blog/archive/2020/Sep-24.html">become even more strict with App Review</a> so we can actually trust that apps we download from the store <em>aren’t</em> scams. The problem is not so much App Review, but rather the fact that if you don’t pass App Review <em>you cannot exist on iOS at all.</em> This simple fact has two notable repercussions:</p>

<ol>
  <li>The overall quality of apps in the App Store has decreased, since App Review must accommodate <em>all</em> apps that want to be on the platform, not just the “good” ones.</li>
  <li>Apps that don’t fit Apple’s philosophies — like emulators, clipboard managers, virtual machines, command-line shells, etc. — can never officially exist on iOS.</li>
</ol>

<p>Sure, Clip can’t be approved because it uses private APIs which could break at any time — but is it really better for the platform that clipboard managers can’t exist <em>at all</em>, rather than just be available for those who really want it? I’ve used a clipboard manager on my Mac for years now and have yet to see any negative effect, so it seems strange to me I can’t make the same decision for my iPad where it would be even more useful (especially for writing this blog post!).</p>

<p>What, then, should Apple do to fix this situation? Based on my experience with AltStore, I’m confident the only reasonable long-term solution is to allow some form of sideloading. This would actually allow Apple to be even <em>more</em> strict with App Review, since apps that didn’t follow the guidelines <em>could still be installed</em>, rather than outright banned from the platform. Antitrust complaints would almost immediately disappear, and Apple would still maintain control over the central place for apps.</p>

<p>Most importantly though: I do believe iOS would suffer if the App Store was no longer <em>the</em> place to download apps. For that reason, <strong>any sideloading solution should be cumbersome enough that the App Store remains the central place to download apps</strong>. Having one central place to download apps is a tremendous usability win, and lowering the bar for sideloading too much might tempt developers who otherwise would’ve just put their app in the App Store. In other words, the App Store should remain the way to download all apps allowed by App Review; only apps that aren’t allowed in the App Store should be distributed separately.</p>

<p>Given these constraints, I see two possible sideloading solutions.</p>

<h2 id="option-1-gatekeeper-for-ios">Option 1: Gatekeeper for iOS</h2>

<p>I’ll start with what I believe is the most straightforward solution: bringing macOS’s Gatekeeper feature to iOS. Gatekeeper is a great security feature that prevents you from launching apps unless they have been signed with a “Developer ID” certificate and notarized with Apple. What does this mean? Basically:</p>

<ol>
  <li>Notarization allows Apple to scan all apps for known malware before distribution.</li>
  <li>Malicious apps can be remotely killed by revoking their Developer ID certificate, allowing Apple to block installations if needed — despite not being in the App Store.</li>
</ol>

<p>A hypothetical Gatekeeper for iOS would function very similarly. Disabled by default, users would be able to choose to allow installing apps from outside sources as long as the apps are properly signed and notarized. The sandbox would remain in place, so apps would still need to explicitly ask permission to access sensitive data/hardware (photos, camera, microphone, etc), and the apps would be 100% removed when deleted from the home screen. Additionally, Apple already prevents Mac apps from using certain features when not distributed through the Mac App Store (such as iCloud), so Gatekeeper for iOS should also restrict what apps can do without going through App Review.</p>

<p>I do expect one major difference from macOS: I don’t think <em>on-device</em> sideloading should be allowed. Instead, <strong>Apple should require you to use a Mac or PC to sideload apps over lightning (/USB-C)</strong>. Letting iOS devices sideload apps directly would certainly be more convenient for legitimate use-cases like AltStore (as mocked-up in this great <a href="https://zachknox.com/2020/08/17/what-if-developer-id-came-to-ios.html">“informal design document” by Zach Knox</a>), but I’m worried such a low bar would make it easily abused by malicious individuals. By requiring a desktop computer, you’d need to go through the same cumbersome process for <em>each</em> app installation (and app update). This would implicitly force users to contemplate whether each app they want to sideload is worth the effort, reducing chances of accidentally installing malware.</p>

<p>Of course, there’s another reason why sideloading should remain complicated: should it be <em>too</em> easy, what’s to stop apps from exiting the App Store en masse like they’ve done <a href="https://9to5mac.com/2015/12/01/sketch-leaves-mac-app-store/">with the Mac App Store</a>? Developers left the Mac App Store because distributing apps via the web was ultimately more convenient than dealing with App Review, and I’m worried the same thing would happen on iOS. Requiring a computer, however, would still allow developers to distribute apps not allowed in the App Store, while also raising the barrier-to-entry enough to keep the App Store as the preferred method to distribute apps.</p>

<h2 id="option-2-expanded-free-developer-account-sideloading">Option 2: Expanded Free Developer Account Sideloading</h2>

<p>Rather than introduce a new feature, Apple could instead decide to just expand upon the existing sideloading feature used by AltStore. When Xcode 7 first introduced sideloading, users were required to re-sign their applications every 3 months to prevent them from expiring. This was annoying, but understandable in order to dissuade developers from using it instead of the App Store. About a year later though, this time limit was reduced from 3 months to just <em>7 days</em>. In practice, having to refresh apps every week is too much of a burden for continued app usage, especially when the process involves connecting to your computer. Furthermore, iOS also limits you to installing only 3 sideloaded apps at a time; if you want to install a 4th, you have to delete another one first.</p>

<p>By simply removing the 3-app limit and extending app expiration back to 3 months (or longer!), suddenly this existing feature <em>could</em> be reasonably used to distribute apps. Just like with a Gatekeeper approach, all iOS security protections such as the sandbox would remain in place. A computer would still be necessary like it is today, resulting in the same benefits I mentioned above. Basically, it would be like AltStore but without having to refresh your apps every 7 days. Most importantly for Apple though, they could easily spin such a change as “improving the development experience for students” rather than as an explicit response to App Store controversies — implicitly leaving it up to AltStore (or others) to leverage it and turn into a legitimate distribution method while relieving antitrust pressure.</p>

<p>However, compared to Gatekeeper this does come with some notable downsides. Because each app is self-signed, there’s no easy way for Apple to remotely disable a malicious app (since each user’s copy has a different signing certificate). Resigning apps can mess with entitlements, such as accessing the keychain or app groups. Self-signed apps also lose access to certain cross-platform functionality like Handoff, which normally requires the same developer team for both Mac and iOS for security reasons. These trade-offs are the same that exist today with AltStore and are mostly manageable, but might become a bigger issue at scale.</p>

<h2 id="so-what-will-apple-do">So what will Apple do?</h2>

<p>At this point, I think the real question is not whether Apple will expand support for sideloading, but whether they’ll do so before legislation forces them to. <a href="https://9to5mac.com/2020/09/08/second-apple-antitrust-investigation-in-two-days-as-australia-opens-one/">Australia</a>, <a href="https://9to5mac.com/2019/08/08/another-antitrust-investigation/">Russia</a>, <a href="https://www.theverge.com/2020/6/16/21292651/apple-eu-antitrust-investigation-app-store-apple-pay">the EU</a>, and <a href="https://www.bloomberg.com/news/articles/2020-06-26/apple-s-app-store-rules-scrutinized-in-u-s-antitrust-probe">the United States</a> are all independently investigating Apple and the App Store for antitrust practices, and it would take just <em>one</em> of them to pass a law requiring Apple to allow apps from outside sources. I want to believe Apple knows this and is planning their own solution, but I’m worried they won’t see the writing on the wall until it’s too late.</p>

<p>AltStore has proven it’s possible to embrace sideloading without threatening the central App Store model — as long as it remains sufficiently more inconvenient than the App Store. Either one of the above options would meet that criteria, but personally I think the Gatekeeper approach is best for the platform. The App Store would remain <em>the</em> place to download apps, but any apps that simply can’t be in the App Store could still be sideloaded via a computer. Apps would be signed with the developer’s Developer ID and notarized, allowing Apple to remote kill any malicious apps that pop-up. Just like macOS, but without compromising any iOS security.</p>

<p>Regardless of which option Apple chooses, by requiring a computer Apple could continue positioning iOS devices as “managed devices” (or “consoles”, <a href="https://mjtsai.com/blog/2020/08/18/app-consoles/">depending on who you ask</a>), while also sticking to their rationale that the Mac is the tool for tinkerers who want to mess with their devices. Plus, either solution would most likely prevent Epic from launching their own Epic Games app store due to the complexity — another benefit for Apple.</p>

<p>Thankfully though, we have some power to shape how iOS evolves. The App Store will almost certainly be the main topic of discussion for the next year in the Apple community, and historically major grievances like this are addressed in the next major iOS version. To name a few:</p>

<ul>
  <li>iPhone OS 3: Cut, Copy, and Paste
    <ul>
      <li><a href="https://daringfireball.net/2007/08/clipboard_and_arrows">“Clipboard and Text Selection : iPhone :: Arrow Keys : Original Macintosh”</a> by John Gruber</li>
      <li><a href="https://gizmodo.com/iphone-copy-and-paste-between-applications-is-here-but-5039256">“iPhone Copy and Paste Between Applications Is Here, But Not from Apple”</a> by Jesus Diaz</li>
    </ul>
  </li>
  <li>iOS 4: Multitasking
    <ul>
      <li><a href="https://www.theregister.com/2009/09/09/spotify_iphone_app/">“Spotify on iPhone: nice app, but no multitasking”</a> by Andrew Orlowski</li>
      <li><a href="https://tidbits.com/2010/02/08/does-the-iphone-os-need-multitasking/">“Does the iPhone OS Need Multitasking”</a> by Adam Engst</li>
    </ul>
  </li>
  <li>iOS 5: Notification Center
    <ul>
      <li><a href="https://techcrunch.com/2009/07/12/push-notifications-on-the-iphone-are-great-but/">“Push Notifications on the iPhone Are Great, But…”</a> by MG Siegler</li>
      <li><a href="https://www.macstories.net/stories/ios-notifications-no-more-no-less/">“iOS Notifications: No More, No Less”</a> by Federico Viticci</li>
    </ul>
  </li>
  <li>iOS 9: Stability improvements
    <ul>
      <li><a href="https://marco.org/2015/01/04/apple-lost-functional-high-ground">“Apple has lost the functional high ground”</a> by Marco Arment</li>
    </ul>
  </li>
</ul>

<p>By keeping the conversation about the App Store going, we’re letting Apple know this is something we care strongly about. Who knows, maybe with enough noise Apple will adjust their plans for iOS 15 and fix this App Store mess once and for all 🤞</p>

<p>My intention was never to go to war with Apple; Apple remains my favorite company, and I am extremely thankful for the opportunities they’ve given me as a developer. All I wanted was to positively shift the status quo towards something better for everyone. Rather than refuting countless straw man arguments, I decided to <em>prove</em> there was another way forward — a way to embrace sideloading without compromising the benefits of the App Store. Today, millions of people are now sideloading apps with AltStore — onerous restrictions and all — and the App Store is in no worse position for it.</p>

<p>All I care about is distributing my apps to anyone who wants them. Please, Apple, just let me do that 💜</p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="altstore" /><category term="app store" /><summary type="html"><![CDATA[One year ago, I launched AltStore as a brand new way to sideload apps not allowed in the App Store, including my Nintendo emulator Delta. Since then, the conversation regarding sideloading and Apple’s control over the App Store has grown tremendously. In just the past year:]]></summary></entry><entry><title type="html">Introducing Clip</title><link href="http://rileytestut.com/blog/2020/06/17/introducing-clip/" rel="alternate" type="text/html" title="Introducing Clip" /><published>2020-06-17T00:00:00+00:00</published><updated>2020-06-17T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2020/06/17/introducing-clip</id><content type="html" xml:base="http://rileytestut.com/blog/2020/06/17/introducing-clip/"><![CDATA[<p>One year ago, I was preparing for the upcoming launch of <a href="https://altstore.io">AltStore</a> — my attempt at building an alternative App Store for non-jailbroken devices (<a href="https://www.theverge.com/2019/10/4/20791856/apple-ios-app-store-riley-testut-altstore-delta-nintendo-emulator-release">maybe you’ve heard of it</a>). I originally built AltStore as a way to distribute Delta, but soon pivoted towards a more general distribution platform for all sideloadable apps. However, if I was going to launch a whole app store and frame it as such, surely there needs to be more than just one app in there, right?</p>

<p>Well, that’s where Clip comes in!</p>

<p>Clip is a clipboard manager for iOS that can run in the background indefinitely, listening for changes to the clipboard and saving your clippings for later use. Normally this would be impossible without jailbreaking, but Clip uses several workarounds to achieve this functionality within the constraints imposed by iOS. Unfortunately, despite working just fine these workarounds are all against App Store rules…which is what makes Clip perfect for AltStore 🎉</p>

<p><img title="Clip Main Screen" src="https://user-images.githubusercontent.com/705880/63391950-34286600-c37a-11e9-965f-832efe3da507.png" width="375px" /><br />
<em>Clip’s main (and only) screen, displaying all your recent clippings.</em></p>

<p>For this initial version, I’ve <em>really</em> focused on the core experience of Clip running in the background and saving all clippings. This means Clip most likely does not have the breadth of features you’d find in an App Store clipboard manager, but what it <em>does</em> do, no App Store app can match (yet?).</p>

<p><strong>Main Features</strong></p>
<ul>
  <li>Monitor clipboard even when Clip is in background.</li>
  <li>Save text, URLs, and images copied to the clipboard.</li>
  <li>Copy, delete, and share clippings.</li>
  <li>Customizable history limit.</li>
</ul>

<p>If you’ve been wanting a true clipboard manager for iOS as much as I have, give Clip a try! Just like Delta, you can download Clip directly from the “Browse” tab of <a href="https://altstore.io">AltStore</a>. As with all my AltStore apps, the complete Clip source code is <a href="https://github.com/rileytestut/Clip">available on GitHub</a>, so you’re also welcome to compile it yourself with Xcode if you’d prefer.</p>

<p>…but wait, if I didn’t want to launch AltStore with just one app, why did I wait till <em>now</em> to launch Clip? Well about that…turns out, getting to this point was much more effort than I ever expected 😅 So if you’re interested in the many challenges I had to overcome while developing Clip, the rest of this blog post is for you 👌</p>

<h2 id="challenge-1-run-clip-in-background-indefinitely">Challenge 1: Run Clip in Background Indefinitely</h2>

<p>Due to iOS restrictions on what apps are allowed to do, there were two crucial pieces of functionality I needed to find workarounds for in order for Clip to be a “real” clipboard manager:</p>

<ul>
  <li>Run in background indefinitely.</li>
  <li>Access clipboard while in background.</li>
</ul>

<p>The first problem dates all the way back to iOS 4 when multitasking was first introduced. There is simply no official way for apps to run indefinitely in the background; when you leave an app, it is suspended in the background to save energy. For Clip to work though, it needs to continuously listen for clipboard changes, which (unsurprisingly) doesn’t work when suspended.</p>

<p>As it turns out, I’m not the first person to try and make an iOS clipboard manager that can run in the background. My favorite Mac clipboard manager <a href="https://tapbots.com/pastebot/">Pastebot</a> actually began life as an iOS app, and over ten years ago (!!) its developers came up with a creative workaround for this problem. As explained <a href="http://web.archive.org/web/20100806185515/http://tapbots.com/blog/pastebot/pastebot-music-in-background">on the Tapbots blog</a>:</p>

<blockquote>
  <p>About a week later (after iOS4’s release), Paul came up with an idea that would actually allow Pastebot to run in the background. Yes, you heard that right. It was a bit of a gamble, but it did not use any private API’s. All we want is to make Pastebot work in the way we always intended it to. The idea is to have a silent audio clip play in the background. This would use one of Apple’s backgrounding APIs that allows music to play in the background. Turns out it works flawlessly. You can finally copy from your Mac or on your iPhone without having to open Pastebot after each copy.</p>
</blockquote>

<p>Unfortunately — but not unexpectedly — Apple rejected that Pastebot update, so this workaround never actually shipped with Pastebot. I couldn’t imagine why this method <em>wouldn’t</em> still work today though, so I decided to try it out.</p>

<p>First steps first, I added the <code class="language-plaintext highlighter-rouge">audio</code> <code class="language-plaintext highlighter-rouge">UIBackgroundMode</code> to Clip’s <code class="language-plaintext highlighter-rouge">Info.plist</code> to prevent iOS from suspending Clip as long as we’re playing audio. Using a silent audio file I made with Garageband, I wrote some code to “play” <code class="language-plaintext highlighter-rouge">Silence.m4a</code> on loop, and also present local notifications every second (so I could track Clip running in the background). I then installed Clip to my phone, launched it without Xcode attached, and returned to the home screen. A notification appeared — but I kept waiting since I knew iOS apps could run for a few seconds before getting suspended. 5 seconds passed…then 10 seconds….then 30….and notifications kept appearing each second. I happily let it run for another several minutes, but it soon became apparent this would work after all! 🎉</p>

<p>One challenge solved, one more to go.</p>

<h2 id="challenge-2-access-clipboard-while-backgrounded">Challenge 2: Access Clipboard While Backgrounded</h2>

<p>On iOS, you access the contents of the clipboard via the <code class="language-plaintext highlighter-rouge">UIPasteboard</code> API. As of iOS 9, however, calling this API from the background will fail, preventing random apps from snooping on your clipboard from the background. Obviously this was a big problem for Clip, so I had to somewhat think outside the box to come up with a solution.</p>

<p>I hypothesized that iOS might not count app extensions as being “backgrounded” — even if their host app is — so I started experimenting with different app extensions. As luck would have it, from trial &amp; error I discovered this background restriction <strong>did not apply to Audio Unit extensions</strong>. This was huge! What exactly are Audio Unit extensions though? They’re basically audio effect plug-ins that other apps can use to manipulate audio in real time. Normally they’re loaded by <em>other</em> apps besides their parent app — such as when GarageBand loads 3rd party effects — but there’s no reason the parent app can’t also launch the extension itself. I moved all clipboard tracking logic into a separate Audio Unit extension, and since I was already playing silent audio to run in the background via <code class="language-plaintext highlighter-rouge">AVAudioEngine</code>, I piped that audio stream through the Audio Unit extension to make sure it was always running alongside Clip. Clip could <em>finally</em> monitor the clipboard while running indefinitely in the background, which meant it was time to polish up a 1.0.</p>

<p><img title="Xcode App Extension Template Picker" src="https://user-images.githubusercontent.com/705880/84836734-30da2700-afeb-11ea-9436-8c948b706ba8.png" width="80%" /><br />
<em>Some of the available app extensions in Xcode.</em></p>

<p>A month later Clip 1.0 was more-or-less ready for launch, so I paused development to finish working on AltStore. At this point, I had two distinct apps ready for AltStore’s launch — Delta and Clip — so I planned all launch material around this: AltStore wasn’t just a way to download emulators, it was a way to download <em>all</em> sorts of apps not allowed in the App Store! Clip was central to this message, and by including it in AltStore at launch I hoped to solidify that.</p>

<h2 id="challenge-3-access-clipboard-while-backgrounded-on-ios-13">Challenge 3: Access Clipboard While Backgrounded <em>on iOS 13</em></h2>

<p>Unfortunately…things did not go as planned. The <em>night before</em> I released AltStore, I ran Clip through some last minute testing…and discovered Audio Unit extensions could no longer access the clipboard in the background on iOS 13! iOS 13 had been released earlier that week, but I had been so busy preparing AltStore and Delta for launch I had forgotten to test Clip on iOS 13 up until that point 🤦‍♂️ Not to mention, I discovered this at around 3am during my final rounds of testing, so I just didn’t have time to look into it more. Reluctantly, I ended up cancelling Clip’s launch, despite already <a href="http://rileytestut.com/blog/2019/09/25/introducing-altstore/">writing about Clip in my AltStore blog post</a> 🙁</p>

<p>Once things had calmed down a bit post-launch, I looked into Clip more. I found that it wasn’t just Audio Unit extensions that could no longer access the clipboard in the background; <em>all</em> app extensions were now forbidden. This was…not the outcome I was hoping for, and was stumped for a while on how to proceed. That is, until one day a thought occurred to me: app extensions can’t access the clipboard in the background, <em>but what about if they’re in the foreground</em>? If there was some app extension that could run in the foreground on-demand in order to retrieve the clipboard, that might just work…right? I quickly clicked “Add Target” in the Clip Xcode project and reviewed all available app extensions, looking for one that might be usable. Most I could dismiss immediately (such as anything without a UI, or anything that can’t be initiated programmatically), but one caught my attention the moment I saw it: Notification Content extension.</p>

<p>Notification Content extensions are run whenever the user opens a notification with an identifier supported by the extension. Most importantly, they can display a fully custom, dynamic UI inside the notification itself. The only question was: would iOS consider this to be running in the “foreground”? Only one way to find out! I added a Notification Content extension target, added a simple <code class="language-plaintext highlighter-rouge">print(UIPasteboard.general.string)</code> to print the contents of the clipboard when the extension launches, then had Clip repeatedly schedule local notifications. I ran Clip on my device, returned to the home screen, then waited for a local notification to appear. Once one did, I pulled it down to open it and…my iPhone’s clipboard contents were printed in Xcode’s console! It worked! 🥳</p>

<p><img title="Notification Content app extension" src="https://user-images.githubusercontent.com/705880/84835557-b4dedf80-afe8-11ea-94c5-52731b3ac15c.gif" /><br />
<em>Notification Content app extension in action.</em></p>

<p>From here, I spent the next week or so shaping this proof-of-concept into a shippable product. Since I had already planned to ship Clip with the Audio Unit extension workaround, it didn’t take long once I had refined this new workaround before Clip was once again in a shippable state. <a href="https://mobile.twitter.com/altstoreio/status/1205597959699582977">I (re-)announced Clip on Twitter</a> along with the first downloadable beta (available to my patrons). I continued to beta test Clip for the next couple months, finishing up what I once again thought would be Clip 1.0. The Notification Content extension appeared to be working well, and I soon released what I considered to be the Clip 1.0 GM build to beta testers. In the release notes for that version, I even mentioned the public release was imminent! I was so sure the time had finally come to release Clip, and I was ready.</p>

<h2 id="challenge-4-ios-1331-breaks-sideloaded-app-extensions">Challenge 4: iOS 13.3.1 Breaks Sideloaded App Extensions</h2>

<p>Naturally, that’s when my iOS update woes began. On January 28 — shortly after I released Clip 1.0 GM to testers — Apple released iOS 13.3.1, a seemingly minor update by all appearances except for one thing: <em>all</em> apps installed with AltStore crashed on launch 😅 Long (but frantic) story short, it turned out for whatever reason iOS 13.3.1 refused to launch any apps signed with free developer accounts (aka, AltStore apps and any apps using Xcode without a paid developer account) that contained dynamic frameworks <em>or</em> app extensions.</p>

<p>The dynamic framework restriction was annoying but not impossible to work around, so I managed to release updated versions of AltStore and Delta converted to entirely use static libraries vs dynamic frameworks within a couple weeks (just like the good ol’ days of iOS development!). As for the app extension restriction…Clip’s main functionality <em>relied</em> on an app extension, so it seemed it was impossible for Clip to work, and I reluctantly paused development (again) to focus on AltStore and Delta.</p>

<p>Thankfully, this issue ended up resolving itself. iOS 13.4 was released a couple months later, which once again allowed sideloaded apps to use frameworks and app extensions. This didn’t matter too much for AltStore and Delta since I had already successfully migrated to static libraries (which deserves its own blog post…), but it meant other apps people were sideloading with AltStore started working again too (since almost every app uses frameworks nowadays). Additionally, now that app extensions were supported again, it would be possible to release Clip!</p>

<h2 id="challenge-5-app-extensions-count-towards-sideloaded-app-limit">Challenge 5: App Extensions Count Towards Sideloaded App Limit</h2>

<p>Except…with 13.4 came another big caveat (of course). While installing and running sideloaded apps with app extensions worked fine, app extensions were now included in the 3 sideloaded apps limit enforced by iOS. In other words, <em>every</em> sideloaded app extension now counted as a sideloaded app, meaning an app containing just 1 app extension would take up 2 sideloaded app slots. Since AltStore itself required 1 slot, this meant apps containing more than 1 app extension could not be installed by AltStore anymore. More importantly, however, any apps containing more than 2 app extensions <strong>could not be sideloaded period</strong>, even with Xcode (unless you are a paid developer).</p>

<p>As with most things Apple, it was hard to guess whether this change was intentional, or was simply a bug introduced simultaneously with the 13.3.1 dynamic frameworks bug. I was cautiously optimistic it was the second, and hoped to see it fixed soon. Regardless, there was little I could do on my end to work around it, so I had to accept this new restriction (even if it ended up being temporary) and adjusted my AltStore and Delta roadmaps to de-prioritize any features relying on app extensions (such as Siri Shortcuts support for AltStore 💔).</p>

<p><em>sigh</em> Apple giveth, Apple taketh away.</p>

<h2 id="challenge-6-actually-launching-clip">Challenge 6: Actually Launching Clip</h2>

<p>For a few weeks, there was some stability: neither iOS 13.4.1 nor the 13.4.5 betas drastically changed how the system treated sideloaded apps. App extensions still counted towards the sideloaded app total, but honestly after the previous two updates I considered no more surprise restrictions/bugs a win. This streak continued until Apple released “iOS 13.5 beta 3”, a renaming of iOS 13.4.5 which included the first version of <code class="language-plaintext highlighter-rouge">ExposureNotification.framework</code>, Apple’s COVID-19 contact tracing framework.</p>

<p>Thankfully, that wasn’t the only change in 13.5. As usual, I downloaded the beta to see if there were any changes for sideloaded apps…and to my delight I discovered app extensions no longer counted towards the sideloaded app limit 🥳 For the first time in almost 6 months, it seemed like I would <em>finally</em> be able to release Clip after all. Once 13.5 was released in late May and I confirmed the fix was still present, I once again set to work preparing Clip for release.</p>

<p>…and that’s where we are today! Phew! Almost 9 months after it was initially supposed to launch, Clip is now available for everyone to download through AltStore. I hope Clip will serve as a valuable tool for anyone looking for a simple iOS clipboard manager, and I would <em>love</em> to hear all your feedback on how I can improve Clip in the future 💜</p>

<p><img title="Clip AltStore Page" src="https://user-images.githubusercontent.com/705880/84836281-4bf86700-afea-11ea-877e-e667e57c3252.PNG" width="375px" /><br />
<em>Clip’s product page in AltStore.</em></p>

<p>But on that note, there is one last thing (I promise) about future features…</p>

<h2 id="feature-preview-custom-keyboard">Feature Preview: Custom Keyboard</h2>

<p>Beyond the core features in Clip 1.0, there’s one feature in particular I’ve been particularly excited to work on: a keyboard extension for quick access to clippings. While preparing this launch I spent some time prototyping such a keyboard, but quickly got carried away and ended up polishing it into a “real” feature. For that reason, I’m also happy to announce <strong>Clip 1.1</strong>, the first major update to Clip that will come with this new custom keyboard:</p>

<p style="text-align:center">
<img class="selfie" title="Clip Keyboard - Light" src="https://user-images.githubusercontent.com/705880/84842227-70a80b00-aff9-11ea-8b04-bedb1f49c4a7.PNG" width="375px" />
<img class="selfie" title="Clip Keyboard - Dark" src="https://user-images.githubusercontent.com/705880/84842231-7271ce80-aff9-11ea-9272-e128aeceb95b.PNG" width="375px" /><br />
<em>Light &amp; dark versions of the Clip keyboard with the standard Mail toolbar.</em>
</p>

<p>Clip 1.1 will be a free update to Clip once finished, and a beta version is available <strong>now</strong> for all my patrons via AltStore. As a reminder, I will be <a href="https://twitter.com/rileytestut/status/1268634685195735040">donating <em>all</em> my Patreon earnings for the month of June</a> to causes supporting <a href="https://blacklivesmatters.carrd.co">Black Lives Matter</a>, so if you’re interested in beta testing Clip’s custom keyboard (or any other beta versions of my apps) while also supporting a great cause, feel free to <a href="http://patreon.com/rileytestut">donate to my Patreon here</a> 🙂💜</p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="altstore" /><category term="clip" /><summary type="html"><![CDATA[One year ago, I was preparing for the upcoming launch of AltStore — my attempt at building an alternative App Store for non-jailbroken devices (maybe you’ve heard of it). I originally built AltStore as a way to distribute Delta, but soon pivoted towards a more general distribution platform for all sideloadable apps. However, if I was going to launch a whole app store and frame it as such, surely there needs to be more than just one app in there, right?]]></summary></entry><entry><title type="html">Introducing AltStore</title><link href="http://rileytestut.com/blog/2019/09/25/introducing-altstore/" rel="alternate" type="text/html" title="Introducing AltStore" /><published>2019-09-25T00:00:00+00:00</published><updated>2019-09-25T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2019/09/25/introducing-altstore</id><content type="html" xml:base="http://rileytestut.com/blog/2019/09/25/introducing-altstore/"><![CDATA[<p>I honestly can’t believe I’m finally writing about all of this. Everything in this blog post is something I’ve been working on in some form or another for the past several years. In order to make sure I didn’t shoot myself in the foot by revealing too much, however, I didn’t allow myself to talk about anything other than Delta during the whole process 😅 But now, finally, it’s time to reveal the <em>other</em> big project I’ve been working on: <a href="https://altstore.io">AltStore</a>.</p>

<p><img src="https://user-images.githubusercontent.com/705880/65605569-30ca6080-df5e-11e9-8dfb-15ebb00e10cb.PNG" width="375" height="667" /></p>

<p>So, what is AltStore? AltStore is <strong>an alternative app store for non-jailbroken devices</strong>. Unlike other unofficial app stores today, AltStore does <em>not</em> rely on enterprise certificates, which Apple has been cracking down on more and more recently. Instead, it relies on a lesser known developer feature that allows you to use your Apple ID to install apps you’ve developed yourself with Xcode, Apple’s development toolkit. This is intended for people who might otherwise be unable to purchase a $99/yr developer account themselves (such as students) — but as it turns out there’s no technical reason why it’s limited to just apps installed from Xcode.</p>

<p>AltStore is a fully native, sandboxed iOS application that allows you to sideload apps by essentially “tricking” your phone into thinking it’s installing apps that you made yourself, when really they can be any apps whatsoever. Since this is an actually supported installation method by Apple, it’s far less fragile than other distribution methods in the past (such as our old friend the Date Trick to install GBA4iOS 💜). Similarly, since there’s no single enterprise certificate to revoke (because technically every user now has their own developer certificate using this process), Apple can’t simply shut it down with the press of a button like they have with some 3rd party app stores (until they receive a new certificate in a week or so, of course).</p>

<p>For this distribution method, AltStore requires your Apple ID and password to communicate on your behalf with Apple’s developer servers. I’ve done everything I can to ensure these credentials are handled properly (i.e. it’s never sent to any 3rd party server, only sent directly to Apple for authentication, and then stored securely in the device’s keychain so nothing else can retrieve it), but since it doesn’t matter <em>what</em> Apple ID is provided, you are more than welcome to create throwaway accounts if desired. Once AltStore has configured your account for you, AltStore then “resigns” (or as I call it in AltStore, “refreshes”) the application with your Apple ID to ensure all normal iOS security checks pass and treat the app as if it’s an app you’ve built yourself.</p>

<p>However, this method was certainly not without its challenges; Apple has put several restrictions in place for this distribution method to prevent exactly this use case, which (they hoped) would severely limit what people could do with it. As it turns out, these restrictions are exactly what I’ve been trying to work around for the past few years, and I’m very happy with the results 😄</p>

<h3 id="altserver">AltServer</h3>

<p>Unlike apps distributed with a paid Apple Developer account, you can’t install apps distributed with a free Apple ID over-the-air. This means that while we can prepare apps for installation from the AltStore app, unfortunately there is no way to actually install apps directly from the iOS device. However, as it turns out this restriction does <em>not</em> apply to installing apps via iTunes WiFi sync, which is where AltServer comes in.</p>

<p>AltServer is a desktop companion app for macOS/Windows that does nothing but just silently run in the background listening for incoming AltStore connections. When a connection is formed, AltStore sends a resigned/refreshed app to AltServer over WiFi, which then uses the same underlying iTunes WiFi sync infrastructure as Apple to wirelessly install the app back to your device.</p>

<p>Since (obviously) there is no AltStore on device to install AltStore in the first place, AltServer is also responsible for initially installing AltStore onto your device. Once AltStore has been installed, however, you can do everything else from the app itself (as long as you are on the same WiFi network as AltServer and iTunes WiFi sync is enabled).
 </p>
<h3 id="refreshing-apps">Refreshing Apps</h3>

<p>All apps signed with a free Apple ID are only valid for 7 days, at which point they expire and can no longer be launched. To compensate for this, AltStore will <em>periodically refresh all your installed apps in the background</em>, or alternatively you can manually refresh the apps yourself from within AltStore. Once they’ve been refreshed, they won’t expire for another week.</p>

<p>Right now, this is using the existing iOS Background Fetch API, which allows an app to run in short bursts in the background at the system’s discretion. Unfortunately there’s not much more control beyond this, and it’s random whether the system chooses a time where the device is connected to the same WiFi as AltServer. However, the more you use AltStore, the more often iOS will let it try to refresh apps in the background, so as long as you open the app every once in a while, AltStore and AltServer should be able to find each other at least <em>once</em> over the course of the week. Even better, iOS 13 introduced new backgrounding APIs that are much better for this use case, and I plan to use them as soon as I can. Imagine a Shortcut to refresh your apps that automatically runs in the background whenever you connect to your home WiFi… 🙂</p>

<h3 id="installing-more-than-3-apps">Installing More than 3 Apps</h3>

<p>The last major restriction is that an iOS device may only ever have at most 3 apps installed using this method, even if they come from different Apple IDs. This was by far the most frustrating one to deal with, but thankfully I was able to find a workaround in time. Whenever an app is installed using this method, its “provisioning profile” is also stored on-device alongside other provisioning profiles from other apps in a separate location. As it turns out, iOS doesn’t actually check the presence of apps to see if you’ve exceeded your limit, but instead checks the presence of these provisioning profiles.</p>

<p>While there’s nothing I could do about this from the iOS device itself, as it turns out the same underlying iTunes (WiFi) sync infrastructure I’m using allows you to also install and remove provisioning profiles from devices (since Xcode also requires this ability to manage profiles for developers). Before installing an app, I remove all the existing profiles on the device to make it look to the system like there are no other apps installed, and then once the app is installed I reinstall all the profiles. It’s very simple, but it works.</p>

<h2 id="what-apps-are-available">What apps are available?</h2>

<p>From the beginning, AltStore was intended to serve as a way for developers to distribute entirely new apps that push the boundaries of iOS in ways not possible with Apple’s app review system. AltStore will initially launch with two of my own apps included: <strong>Delta</strong>, my all-in-one emulator I’ve been working on for the past 4+ years, as well as <strong>Clip</strong>, a simple clipboard manager app.</p>

<p>Delta of course is not allowed in the App Store due to Apple’s stance on emulation, but why make a clipboard manager when so many already exist in the App Store? Simple: there is no App Store-approved way for apps to run continuously in the background, which means you need to remember to manually open up these apps for them to save your history. However, since I don’t need to adhere to app review, I can be a little more…creative. Technically, media apps are allowed to run indefinitely in the background so that the user can continue listening to music while performing other tasks. Clip takes advantage of this by playing silent audio on loop while in the background, but in a way that won’t affect whatever else you might be listening to on your phone at the same time. This allows Clip to constantly monitor the device’s clipboard, while also having a negligible effect on battery life (it takes very little energy to “play” the silent audio file I’m using), and I’ve been using it non-stop for the past few weeks or so without noticeable effects.</p>

<p>Post-launch, and once I’ve verified I’ll be able to keep up with demand, I’ll begin working on the ability for anyone to list their own apps inside AltStore, similar to Cydia (but in a more user-friendly way!). This is when the real power of AltStore will come in, and is what I’m definitely most excited for 🎉</p>

<h2 id="when-can-i-start-using-altstore">When can I start using AltStore‽</h2>

<p>Delta, Clip, and AltStore are all officially launching <strong>this Saturday, September 28.</strong> However, because I want to make sure launch goes as smoothly as possible, I’m releasing an AltStore <em>preview</em> that you can download <strong>right now</strong> so I can iron out any remaining issues. If you’d like to help out, <a href="https://altstore.io">just head to the official AltStore website and follow the instructions.</a></p>

<p>To give you all something to download and test everything out, I’ve <a href="http://rileytestut.com/blog/2018/06/21/introducing-delta-lite/">revived Delta Lite, my Swift Playground</a> as a native iOS app. So please, download Delta Lite and help me battle-test everything by reliving some fun NES games! With your help, I can better prepare myself for the big day in just over 72 hours 🙏</p>

<h2 id="great-delta-is-finally-here-what-comes-next">Great, Delta is finally here!! What comes next?</h2>

<p>Well, I have <em>lots</em> of ideas I want to do for AltStore, Delta, and Clip, and now that I’ve built this foundation it will be much easier to rapidly build on top of it. However, there is just one problem: I’ve been trying to figure out how I can actually support myself working on AltStore, Delta, Clip, as well as any other apps I may make. For almost the entire development of Delta, I’ve supported myself by working various freelance jobs, and then spending whatever free time on top of that on my own apps. This works, but it does mean I’m not able to invest as much time as I’d like into my apps, which in turn means it takes much longer to finish them (see: almost 5 year development period for Delta).</p>

<p>I’ve had enough people ask me over the years if there was an official way to support my work that I <a href="https://patreon.com/rileytestut">finally decided to try out Patreon</a>. I’m still planning on freelancing to provide for myself, but the hope is a Patreon will subsidize the amount of money I need to earn by freelancing, thus freeing me up more to work on my own apps. In exchange for becoming a patron, you’ll be able to then <strong>download beta versions of my apps</strong>, which will be listed and installed through AltStore like their non-beta versions (but identified with a “Beta” badge). This way, AltStore, Delta, and Clip can remain free for everyone, but those who donate just get access to the newer features early.</p>

<p>Initially, AltStore will launch with these betas for patrons:</p>

<h3 id="altstore-beta---sideloading-apps">AltStore Beta - Sideloading Apps</h3>
<p>This feature allows you to use AltStore to install <em>any</em> apps — not just those listed in AltStore — and have them be refreshed in the background just like an AltStore app. It currently works for most apps, but apps that are slightly more complex (such as those with certain app extensions) might fail. My priority post-launch is to make this sideloading feature work with as many apps as possible, before later adding support for 3rd party app listings directly in AltStore.</p>

<h3 id="delta-beta---nintendo-ds-support">Delta Beta - Nintendo DS Support</h3>
<p>Surprise, Nintendo DS support is coming to Delta after all 🎉 Initial support for DS games will be <strong>available at launch</strong> in the Delta beta, including support for game saves, save states, and Hold Button. Because it’s still in beta, I’ve yet to add support for the remaining features such as Fast Forward and cheats, but I hope to add those features sooner rather than later post launch (because I want them for me too!).</p>

<h3 id="delta-lite-beta---gameboy-color-support">Delta Lite Beta - Gameboy Color Support</h3>
<p>In addition to Delta Lite, there will also be a “beta” version that supports <strong>both NES games and GBC games</strong>. This is so people who donate on Patreon during the preview receive something special, instead of having to wait a few days to receive the Delta beta.</p>

<p>So yeah, if you’d like to support me working on these apps as my full-time job, I hope you’ll enjoy early access to whatever I’m working on 😊</p>

<h2 id="one-big-wrap-up">One Big Wrap-Up</h2>

<p>Okay, I know this was a lot, so here’s a condensed version with what you need to know:</p>

<ul>
  <li>Delta’s distribution method is AltStore, an alternative app store for non-jailbroken devices.</li>
  <li>AltStore uses your own Apple ID to prepare apps for installation, not some (possibly stolen) enterprise certificate that can be revoked.</li>
  <li>AltStore uses a desktop app AltServer to install apps back to the phone using iTunes WiFi Sync.</li>
  <li>AltStore refreshes apps for you in the background so you don’t need to ever manually refresh them or worry about them expiring.</li>
  <li>You can install more than 3 apps with AltStore.</li>
  <li>AltStore, Delta, and Clip are simultaneously launching <strong>this Saturday, September 28</strong>.</li>
  <li>AltStore preview <a href="https://altstore.io">available for download right now.</a></li>
  <li>You can receive access to beta versions of AltStore, Delta, and more by <a href="https://patreon.com/rileytestut">supporting me on Patreon</a>.</li>
  <li>Beta version of AltStore includes <strong>ability to sideload any app (.ipa file).</strong></li>
  <li>Beta version of Delta includes <strong>support for playing Nintendo DS games.</strong></li>
</ul>

<p>And I think…..that’s everything I’ve been keeping secret for the past several years. Stay tuned as I continue to add features to AltStore, Delta, and Clip, and soon open up AltStore so anyone can be a part of it. iOS is a tremendous platform, but there are definitely missed opportunities to build some <em>amazing</em> apps. My dream is for AltStore to foster an entirely new iOS app ecosystem determined to push the platform to its limits, and I’m committed to making that a reality with all of your help 💜</p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="delta" /><category term="altstore" /><category term="clip" /><summary type="html"><![CDATA[I honestly can’t believe I’m finally writing about all of this. Everything in this blog post is something I’ve been working on in some form or another for the past several years. In order to make sure I didn’t shoot myself in the foot by revealing too much, however, I didn’t allow myself to talk about anything other than Delta during the whole process 😅 But now, finally, it’s time to reveal the other big project I’ve been working on: AltStore.]]></summary></entry><entry><title type="html">Delta - From Part-Time to Full-Time</title><link href="http://rileytestut.com/blog/2018/10/01/delta-from-part-time-to-full-time/" rel="alternate" type="text/html" title="Delta - From Part-Time to Full-Time" /><published>2018-10-01T00:00:00+00:00</published><updated>2018-10-01T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2018/10/01/delta-from-part-time-to-full-time</id><content type="html" xml:base="http://rileytestut.com/blog/2018/10/01/delta-from-part-time-to-full-time/"><![CDATA[<blockquote>
  <p>I am <em>very</em> confident that Delta will be released <em><strong>this summer</strong></em>. Trust me, I’m ready to get Delta out there and begin working on my next projects, so I’m going to do <em>everything</em> in my power to meet that release timeframe.</p>
</blockquote>

<p>😅</p>

<p>As mentioned in that same post, earlier this year I was working for a startup between classes and homework as I finished my senior year of college. My intention was to earn enough money so I could then quit and work on Delta full time in order to finish it by summer’s end. However, despite continuing to work in my free time for the rest of the semester, by the time I graduated I didn’t have anywhere <em>close</em> to enough money to actually sustain myself until I finished Delta. Whoops.</p>

<p>Since it would be significantly more difficult to finish Delta if I were homeless, I realized I needed to find another job to sustain myself in the meantime. As a result, I started working full time for a second company over the summer, slowly saving up enough money to ensure I would be able to pay for rent and groceries and other adulting-things. This prevented me from working on Delta much over the summer, which is why I wasn’t able to get it done by summer’s end, despite the app still remaining relatively close to completion. However, I <em>was</em> able to make enough money to support myself for the rest of the year, which leads me to…</p>

<h2 id="the-good-news">The Good News</h2>

<p>As of today, I have officially quit my job, and for the first time <em>ever</em> am able to work on Delta full time with no other homework/jobs forcing me to divide up my time.  This is <strong>huge</strong>, as I am now able to put in all the necessary effort to finish Delta once and for all 🎉</p>

<p>This week, my plan is to dive back in and continue working on Delta from where I left off and determine the remaining features and tasks necessary to release Delta 1.0. For this reason, I am not announcing a new estimated release date for Delta at this time<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>, but I hope to write another blog post next week with more details.</p>

<h2 id="quick-aside-twitter-hiatus">Quick Aside: Twitter Hiatus</h2>

<p>Some of you may have noticed I’ve been less active on Twitter lately. This is mostly just because Twitter has become more and more stressful and overwhelming for me lately due to everything happening in America right now, but now that I’m working on Delta full time I’m planning on going back to being active on Twitter and answering questions you may have. So please, send any questions to <a href="https://twitter.com/rileytestut">@rileytestut</a> and I’ll do my best to answer them!</p>

<p>—</p>

<p>I know you all are getting tired of waiting for Delta, but now that I have no other priorities competing for my time the days of unexpected delays should finally be over. From now on, expect steady continuous improvements to the app, and occasional blog posts with updates on progress (especially if more unexpected developments arise). And as always, thank you all so much for your incredible patience 💜</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Unofficially, I’m really trying to release Delta before January, if only so I can say Delta wasn’t delayed as much as Kingdom Hearts 3 was 🙃 <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="delta" /><summary type="html"><![CDATA[I am very confident that Delta will be released this summer. Trust me, I’m ready to get Delta out there and begin working on my next projects, so I’m going to do everything in my power to meet that release timeframe.]]></summary></entry><entry><title type="html">Introducing Delta Lite</title><link href="http://rileytestut.com/blog/2018/06/21/introducing-delta-lite/" rel="alternate" type="text/html" title="Introducing Delta Lite" /><published>2018-06-21T00:00:00+00:00</published><updated>2018-06-21T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2018/06/21/introducing-delta-lite</id><content type="html" xml:base="http://rileytestut.com/blog/2018/06/21/introducing-delta-lite/"><![CDATA[<p>For the past few weeks, I’ve been working on a brand new project I’m happy to share with you all: Delta Lite. Delta Lite is a Swift Playground that allows you to play any NES game in the Swift Playgrounds app on your iPad. Despite being a playground, Delta Lite is essentially a complete iOS app, and it supports standard emulation features such as save states and cheat codes, as well as Delta’s unique Sustain Button functionality.</p>

<h2 id="how-does-it-work">How does it work?</h2>
<p>You may be asking, what is Swift Playgrounds? Swift Playgrounds is an iPad app that allows you to write (typically small) Swift programs. Primarily focused on teaching Swift fundamentals, it includes several “Learn to Code” lessons provided by Apple, but you are also able to download additional playgrounds that usually teach specific Swift or iOS development lessons. For more information, I’d recommend checking out <a href="https://www.apple.com/swift/playgrounds/" title="Apple’s website">Apple’s website</a>.</p>

<p>Delta Lite is also a swift playground, but it is far more complex than the ones provided by Apple. Because Delta has been written in Swift, Delta Lite uses the same codebase internally, which means that the program that runs when you open the playground on your iPad is almost identical to the app version of Delta.</p>

<h2 id="why-only-nes">Why only NES?</h2>

<p>Swift Playgrounds only supports programs written in Swift. Unfortunately, the vast majority of emulators are written in C++, which means they cannot be used as-is. To work around this, I came up with a somewhat convoluted solution. I took the Nestopia emulator codebase, and then using <a href="https://github.com/kripken/emscripten" title="Emscripten">Emscripten</a> I compiled the codebase to JavaScript. I included this JavaScript file in Delta Lite, and then I use a hidden web view to run this JavaScript in the background, piping data to and from the web view as needed.</p>

<p>This process was somewhat tricky, so for now I limited it to just NES. There’s no reason I couldn’t add more systems in the future, but I think everyone would be happier if I spent that time finishing Delta itself :-) But yes, this does mean <strong>Delta will launch with NES support as well!</strong></p>

<h2 id="download-instructions">Download Instructions</h2>

<ol>
  <li>Download <a href="https://itunes.apple.com/us/app/swift-playgrounds/id908519492?mt=8">Swift Playgrounds</a> on your iPad from the App Store.</li>
  <li>Tap <a href="https://developer.apple.com/ul/sp0?url=https://deltaemulator.com/feed.json">this link</a> on your iPad, which will launch Swift Playgrounds.</li>
  <li>Tap “Subscribe” on the alert that appears.</li>
  <li>Tap “Get” on the Delta Lite playground in the new “Delta” section.</li>
  <li>Open up the Delta Lite playground, and start playing NES games!</li>
</ol>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="delta" /><category term="delta lite" /><category term="swift" /><category term="playgrounds" /><summary type="html"><![CDATA[For the past few weeks, I’ve been working on a brand new project I’m happy to share with you all: Delta Lite. Delta Lite is a Swift Playground that allows you to play any NES game in the Swift Playgrounds app on your iPad. Despite being a playground, Delta Lite is essentially a complete iOS app, and it supports standard emulation features such as save states and cheat codes, as well as Delta’s unique Sustain Button functionality.]]></summary></entry><entry><title type="html">Delta - Version 1.0 and Beyond</title><link href="http://rileytestut.com/blog/2018/04/08/delta-version-1-0-and-beyond/" rel="alternate" type="text/html" title="Delta - Version 1.0 and Beyond" /><published>2018-04-08T00:00:00+00:00</published><updated>2018-04-08T00:00:00+00:00</updated><id>http://rileytestut.com/blog/2018/04/08/delta-version-1-0-and-beyond</id><content type="html" xml:base="http://rileytestut.com/blog/2018/04/08/delta-version-1-0-and-beyond/"><![CDATA[<p>Naturally, 2 weeks after I wrote my last blog post promising updates every 2 weeks, I realized I was on Spring Break in Europe, and would be unable to write and publish one. “Not a big deal,” I thought, “I’ll just write one when I get home!” Then, of course, I find out there are a <em>lot</em> of assignments for school due in the couple weeks after Spring Break, so I ended up not having time to write a blog post then either….</p>

<p>Welp, I <em>finally</em> have a weekend free from my various projects, so here’s a blog post! 🎉</p>

<p>Since the last blog post emphasized being more transparent, in this post I’m going to continue with that theme and just detail why my life is so busy at the moment, and what that means for Delta now, in the immediate future, and beyond.</p>

<h2 id="why-am-i-so-busy">Why am I so busy?</h2>

<p>The answer to this comes down to two primary reasons:</p>

<ol>
  <li>As it turns out, senior year of college is not the same as senior year of high school 🤷‍♂️ When I was a senior in high school, I was able to work on GBA4iOS 2.0 almost every day after school, allowing me to release the final version in February despite only starting it in July. As a senior at USC, my classes (unfortunately) have far more homework and assignments than my previous years of college, resulting in essentially an asymptotic situation; as time goes by, I continue to get closer to finishing Delta, but the progress is smaller and smaller 🙃</li>
  <li>For the majority of my time not spent working on school assignments, I’m instead contracting for a small USC-based startup. I enjoy the work I’m doing—and most importantly it’s literally paying for my various student needs (s/o to student discounts though)—but it does mean I have even less free time I can devote to working on Delta 😔</li>
</ol>

<h2 id="what-does-the-immediate-future-look-like">What does the immediate future look like?</h2>

<p>I’m just going to be honest. I have exactly 1 month and 3 days until I graduate, and unfortunately it will be filled with school assignments, final exam preparations, and misc. other things requiring my time, so it’s going to be very hectic for me. For that reason, I’m not anticipating making much progress on Delta (which I promise really bums me out too, because usually working on Delta is my reward for finishing my school assignments).</p>

<p>However, as an aside, one of the things keeping me busy is that next weekend <strong><em>my amazing sister is getting married!</em></strong> I could not be more excited for her or her fiancé, they make such an amazing couple! Hopefully you will all forgive her for having her wedding now and contributing to my continuously busy schedule :)</p>

<h2 id="what-about-post-graduation">What about post-graduation?</h2>

<p>Here’s where the good news begins: immediately after graduation, I have no obligations or plans whatsoever! Once I have my diploma in hand (and after a very short trip to Disney World), I’m planning on going home to Dallas and working on Delta non-stop.</p>

<p>In terms of remaining features, Delta <em>really</em> is almost finished. When I’m only able to work on it for a few hours every week or so, these features take a while to complete, but when I’m able to work on them for several hours every day, I can knock them out very quickly! For this reason, I am <em>very</em> confident that Delta will be released <em><strong>this summer</strong></em>. Trust me, I’m ready to get Delta out there and begin working on my next projects, so I’m going to do <em>everything</em> in my power to meet that release timeframe.</p>

<h2 id="what-happens-post-delta-10">What happens post Delta 1.0?</h2>

<p>The release of Delta 1.0 will finally be the end of this years-long endeavor, but that does not mean Delta itself be finished. Once 1.0 is released, I plan on maintaining and updating it just like I would with a normal App Store app, and I’m very excited about some of the updates I have in mind.</p>

<p>While this list is absolutely not definitive, here are some of the plans I have for Delta beyond 1.0 (in no particular order):</p>

<ul>
  <li>Nintendo DS support</li>
  <li>Multiplayer support for SNES and N64 games</li>
  <li>Native Apple TV support</li>
  <li>3D Touch support in controller skins (so you can rest your fingers on the screen but buttons won’t activate unless you press harder)</li>
  <li>Event Distributions (just like GBA4iOS)</li>
  <li>Ability to search for popular cheat codes (rather than always having to find them online and type them in yourself)</li>
  <li>Variable Fast Forward speeds</li>
  <li>Custom filters to alter appearance of games</li>
</ul>

<p>Thankfully, once Delta 1.0 is released, updates will take <em>significantly</em> less time to develop and release. I would love to even release a 1.1 update with some of these features by the end of this summer, but I’m certainly not going to commit to that given the history of Delta’s progress so far 🤷‍♂️</p>

<p>As always, thank you all for staying with me on this very long journey; knowing you all are excited for Delta helps me stay motivated throughout my incredibly busy final semester until graduation, after which I will be able to <em>finally</em> release Delta to the world 😃</p>]]></content><author><name>riley</name></author><category term="blog" /><category term="developer" /><category term="delta" /><summary type="html"><![CDATA[Naturally, 2 weeks after I wrote my last blog post promising updates every 2 weeks, I realized I was on Spring Break in Europe, and would be unable to write and publish one. “Not a big deal,” I thought, “I’ll just write one when I get home!” Then, of course, I find out there are a lot of assignments for school due in the couple weeks after Spring Break, so I ended up not having time to write a blog post then either….]]></summary></entry></feed>