<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>boredcoder411&apos;s blog</title>
    <link>https://boredcoder.dev/blog/</link>
    <description>Writeups on systems, Rust, and software projects.</description>
    <language>en</language>
    <lastBuildDate>Sat, 07 Nov 2026 00:00:00 GMT</lastBuildDate>
    <atom:link href="https://boredcoder.dev/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Picogram: Instagram, trimmed down to the conversations</title>
      <link>https://boredcoder.dev/blog/picogram-minimizing-distractions/</link>
      <guid isPermaLink="true">https://boredcoder.dev/blog/picogram-minimizing-distractions/</guid>
      <pubDate>Sat, 07 Nov 2026 00:00:00 GMT</pubDate>
      <category>ANDROID / PATCHING</category>
      <description>a version-specific ReVanced patch that makes dms the first stop and quiets Instagram&apos;s main feed</description>
      <content:encoded><![CDATA[<p>instagram is where a lot of my conversations happen. opening the app can also mean landing in home or reels, which can easily lead to doomscrolling. i wanted a version that made checking messages feel like the main thing</p>
<p>picogram is a ReVanced patch for Instagram <strong>453.0.0.57.79</strong> (<code>com.instagram.android</code>). it keeps dms and profile in the bottom bar, opens to dms, blocks a small set of feed requests, and stops swipe navigation and pull-to-refresh in reels. the idea is pretty simple: make it easier to get to messages, then leave the rest of the app out of the way</p>
<h2>what the patch changes</h2>
<p>instagram represents its tabs as enum values. the patch replaces the method that builds the tab list with one that returns just dms and profile, then changes the starting destination to dms</p>
<p>the feed filter runs in <code>TigonServiceLayer.startRequestInternal</code>. it reads the request URI and passes it to a small helper bundled with the patch. the helper cancels requests whose paths contain these fragments:</p>
<ul><li><code>/feed/timeline/</code></li><li><code>/feed/reels_tray</code></li><li><code>/clips/home/</code></li><li><code>/clips/discover</code></li><li><code>/clips/get_blend_medias/</code></li><li><code>/discover/topical_explore</code></li></ul>
<p>that’s a short list of routes i wanted to keep out of the main flow. it isn’t a general Instagram network filter; other content reachable from profile, links or messages can still show up</p>
<p>for reels, the patch disables touch input on the relevant <code>ViewPager2</code> and makes <code>ClipsSwipeRefreshLayout.onInterceptTouchEvent()</code> return <code>false</code>. a reel someone sends in a DM can still play, but swiping won’t take you to the next one. i checked that its comments opened too</p>
<h2>a look at the patch</h2>
<p>here’s the tab-list replacement. it creates a new list and adds only the dms and profile entries:</p>
<pre><code class="language-kotlin">method(&quot;LX/00WQ;&quot;, &quot;A04&quot;).addInstructions(0, &quot;&quot;&quot;
    new-instance v0, Ljava/util/ArrayList;
    invoke-dms {v0}, Ljava/util/ArrayList;-&gt;&lt;init&gt;()V
    sget-object v1, LX/03ai;-&gt;A0A:LX/03ai;
    invoke-virtual {v0, v1}, Ljava/util/ArrayList;-&gt;add(Ljava/lang/Object;)Z
    sget-object v1, LX/03ai;-&gt;A0F:LX/03ai;
    invoke-virtual {v0, v1}, Ljava/util/ArrayList;-&gt;add(Ljava/lang/Object;)Z
    return-object v0
&quot;&quot;&quot;)</code></pre>
<p>the request hook finds where the URI is read, then inserts a call to the helper right after it:</p>
<pre><code class="language-kotlin">val register = (instructions[index] as TwoRegisterInstruction).registerA

request.addInstructions(
    index + 1,
    &quot;invoke-static/range {v$register .. v$register}, &quot; +
        &quot;Lcom/inboxonly/FeedBlock;-&gt;check(Ljava/net/URI;)V&quot;
)</code></pre>
<p>the helper checks the path and throws an <code>IOException</code> for the routes in the list:</p>
<pre><code class="language-java">public static void check(URI uri) throws IOException {
    if (uri == null || uri.getPath() == null) return;

    String path = uri.getPath();
    if (path.contains(&quot;/feed/timeline/&quot;)
            || path.contains(&quot;/feed/reels_tray&quot;)
            || path.contains(&quot;/clips/home/&quot;)
            || path.contains(&quot;/clips/discover&quot;)
            || path.contains(&quot;/clips/get_blend_medias/&quot;)
            || path.contains(&quot;/discover/topical_explore&quot;)) {
        throw new IOException(&quot;Blocked feed request&quot;);
    }
}</code></pre>
<p>the reel pager change turns off touch input on <code>ViewPager2</code>; the refresh container stops intercepting the gesture:</p>
<pre><code class="language-smali">const/4 v1, 0x0
invoke-virtual {v0, v1}, Landroidx/viewpager2/widget/ViewPager2;-&gt;setUserInputEnabled(Z)V</code></pre>
<pre><code class="language-smali">const/4 v0, 0x0
return v0</code></pre>
<p>these are the interesting bits, but they aren’t the whole patch. the bundle also has the class and method lookups that help find the right spots in the target apk</p>
<h2>building it</h2>
<p>Instagram’s play download came as split apk files, so i used <a href="https://github.com/AbdurazaaqMohammed/AntiSplit-M">AntiSplit-M</a> to merge them into one apk for patching</p>
<p>the ReVanced patch is written in Kotlin with the bytecode patch api. it targets methods and classes from this release, including obfuscated navigation names like <code>LX/00WQ;</code> and <code>LX/03ai;</code>. i compile the helper to DEX and bundle it as <code>extensions/inbox.rve</code> in the <code>.rvp</code> file</p>
<p>those exact class and method names are also the main limitation: Picogram targets one Instagram build. if Instagram moves the code around, the patch fingerprints and injection points need another look before it can support a newer version</p>
<h2>testing it on a phone</h2>
<p>i applied the bundle to the matching apk and tried it on a Pixel 7. the app opened to dms, the bottom bar showed dms and profile, and a reel opened from a DM kept playing after a swipe instead of advancing</p>
<p>the project was a useful way to learn how bytecode patches fit together, from finding methods in the apk to building a ReVanced bundle and trying it on a device. and for my own use, the result is closer to what i wanted: open the app, check my messages, get on with the day</p>]]></content:encoded>
    </item>
    <item>
      <title>pouf: a language with two destinations</title>
      <link>https://boredcoder.dev/blog/pouf-a-language-with-two-destinations/</link>
      <guid isPermaLink="true">https://boredcoder.dev/blog/pouf-a-language-with-two-destinations/</guid>
      <pubDate>Fri, 06 Nov 2026 00:00:00 GMT</pubDate>
      <category>COMPILERS / SYSTEMS</category>
      <description>one small language, two ways to build things: python for quick experiments and c for systems work</description>
      <content:encoded><![CDATA[<p>i started pouf with a simple idea: write a program in one language, then compile it to either python or c. python makes it easy to try things out; c lets the same project reach into freestanding and low-level work</p>
<p>the fun part isn’t just having two code generators. i want both targets to feel like different ways to run the same language. pouf reads the source, builds an ast, checks bindings, control flow and types, then generates python or c. the syntax stays familiar across both, while the compiler still tells you when a feature doesn’t fit the target you picked</p>
<h2>the language bits</h2>
<p>the basics are familiar: functions, typed parameters and return values, local bindings, loops, enums, arrays and expressions. bindings don’t change unless you mark them <code>mut</code>. enums work with <code>match</code>, including a wildcard arm, so you can see the cases right where you use them. for c, there are also types like <code>Ptr&lt;T&gt;</code>, <code>const&lt;T&gt;</code>, <code>Volatile&lt;T&gt;</code>, <code>Array&lt;T&gt;</code> and <code>Vec&lt;T&gt;</code> to make pointer and data intent visible</p>
<p>here’s an enum and a match in c mode:</p>
<pre><code class="language-pouf">mode c

enum Direction {
    North
    South
    East
    West
}

def describe(direction: Direction) -&gt; Ptr&lt;const&lt;char&gt;&gt; {
    return match direction {
        Direction::North =&gt; &quot;north&quot;,
        Direction::South =&gt; &quot;south&quot;,
        Direction::East =&gt; &quot;east&quot;,
        _ =&gt; &quot;west&quot;,
    }
}</code></pre>
<p>it’s a small example, but it gives you the feel of the syntax. the compiler turns these constructs into the right code for the target, and checks for problems along the way. the shared subset is still growing, so portability means sticking to features both sides support</p>
<h2>what the runtime does</h2>
<p>the runtime isn’t a big standard library of its own. it’s a little bit of support for language features that need it after compilation. in python mode, generated programs use <code>pouf_runtime.py</code> for things like mutable references, option/result values and collection helpers. <code>pouf run</code> sets up the runtime, compiles a python-mode file and runs it; <code>pouf compile</code> writes out the generated python if you want to look at it</p>
<p>in c mode, pouf emits c you can feed into a regular c toolchain. most language features turn into ordinary c declarations, expressions and control flow. the support header, <code>pouf_runtime.h</code>, provides a little machinery for things like <code>Vec&lt;T&gt;</code>: growing its storage, pushing and popping values, clearing it and freeing it. from there, your build can use a host compiler or a freestanding toolchain. pouf doesn’t bundle libc or take care of platform setup for you</p>
<p>some c types and operations don’t have a python equivalent, and python has features that don’t fit the c subset. the compiler checks against the target you chose, and the overlap is smaller than either language on its own. that’s the tradeoff: one language for quick experiments and systems code, without pretending every program will work unchanged on both</p>
<h2>one more example</h2>
<p>this one adds up the squares of even numbers, and can be compiled to c by just changing line 1 from <code>mode python</code> to <code>mode c</code></p>
<pre><code class="language-pouf">mode python

import stdio

def sum_even_squares(numbers: Array&lt;int&gt;, count: int) -&gt; int {
    mut total: int = 0
    for i in range(0, count) {
        let value: int = numbers[i]
        if value % 2 == 0 {
            total += value * value
        }
    }
    return total
}

def main() {
    let numbers: Array&lt;int&gt; = [1, 2, 3, 4, 5, 6]
    let result: int = sum_even_squares(numbers, 6)
    printf(&quot;sum of squares of evens: %d\n&quot;, result)
}</code></pre>
<h2>demo projects</h2>
<p>i&#x27;ve come up with a few demo projects to demo pouf&#x27;s usability:</p>
<ul><li>backend for a hardware renting service</li><li>rewriting parts of <a href="https://github.com/boredcoder411/mboot">mboot</a> userspace</li><li>quick and dirty unix-like os</li><li>cfd data analysis (demo pouf&#x27;s functional features)</li></ul>
<h2>still figuring it out</h2>
<p>there’s still plenty to build. the two targets don’t share every type or feature yet, and real projects are how i find the gaps. python makes it quick to try an idea; c lets me take pouf into constrained environments and systems projects. the goal is simple: keep one language that’s useful in both places, and be clear about where the edges are</p>]]></content:encoded>
    </item>
  </channel>
</rss>
