{"title":"Cracking the Shell - programming","link":[{"@attributes":{"rel":"self","type":"application\/atom+xml","href":"https:\/\/walnut356.github.io\/tags\/programming\/atom.xml"}},{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io"}}],"generator":"Zola","updated":"2026-02-20T00:00:00+00:00","id":"https:\/\/walnut356.github.io\/tags\/programming\/atom.xml","entry":[{"title":"Investigating the SuperNote Notebook Format","published":"2026-02-20T00:00:00+00:00","updated":"2026-02-20T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/inspecting-the-supernote-note-format\/"}},"id":"https:\/\/walnut356.github.io\/posts\/inspecting-the-supernote-note-format\/","summary":"<p>I'm a big fan of eink tablets. I read a lot, I write a lot, I prefer handwritten notes, it's a match made in heaven. I've been using a Kindle Scribe for the past several years - I probably used it as much or more than my phone. Recently, I upgraded to a Supernote Nomad, which has been a lovely experience so far.<\/p>\n<p>One thing that always bothered me about the Scribe is how subpar its notebook exporting is. I don't want to have to be online to do it, I want to be able to do it from my computer rather than my phone, and I want the output file to look exactly like the note I wrote on the screen. Amazon is 0 for 3 on that. Luckily, someone has already solved this problem with a third party app, and I was able to learn a lot from their implementation.<\/p>\n<p>The SuperNote has its own proprietary format for its notebooks, so I figured I'd give it a look. This is mostly going to be about the SuperNote format, but the Scribe format will be my main point of reference.<\/p>"},{"title":"LLDB's TypeSystems Part 2: PDB","published":"2025-07-07T00:00:00+00:00","updated":"2025-07-07T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/lldbs-typesystems-pt-2\/"}},"id":"https:\/\/walnut356.github.io\/posts\/lldbs-typesystems-pt-2\/","summary":"<p>In my previous post, I described implementing PDB parsing as a can of worms. That might have been a bit of an understatement. PDB has been one \"oh, it's gonna be twice as much work as I thought\" after another. Implementing it has revealed many of the same issues as the <code>TypeSystem<\/code> itself: lack of documentation, cryptic implementations, poor naming schemes, and unclear expectations. Despite all that, I was able to get it working.<\/p>\n<p>That means <code>TypeSystemRust<\/code> can be used for executables that target <code>*-gnu<\/code> or <code>*-msvc<\/code>. It's not quite done yet, but this is a massive step towards the <code>TypeSystem<\/code> being fully complete. I want to talk a bit about the process, at least partially for posterity. As we'll see later, PDB itself is <em>also<\/em> not documented very well, so any additional literature could be helpful to someone down the line.<\/p>\n<p>Fair warning, we're getting into the weeds. This is gonna be a long one.<\/p>"},{"title":"LLDB's TypeSystems: An Unfinished Interface","published":"2025-03-28T00:00:00+00:00","updated":"2025-03-28T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/lldbs-typesystems-an-unfinished-interface\/"}},"id":"https:\/\/walnut356.github.io\/posts\/lldbs-typesystems-an-unfinished-interface\/","summary":"<p>Well, it's \"done\". <code>TypeSystemRust<\/code> has a <a rel=\"noopener external\" target=\"_blank\" href=\"https:\/\/github.com\/Walnut356\/llvm-project\/tree\/lldbrust\/19.x\">(semi) working prototype for LLDB 19.x<\/a>. It doesn't support expressions or MSVC targets (i.e. PDB debug info), and there are a whole host of catastrophic crashes, but it more or less proves what it needs to: Rust's debugging experience <em>can<\/em> be improved, and there are worthwhile benefits to a working <code>TypeSystem<\/code> that can't be emulated on other layers of the debugging stack.<\/p>\n<p>If you want to test it out, you'll need to build my fork from source (sorry), but then <code>lldb.exe<\/code> can be used as-is, or you can point a debugger extension like lldb-dap or CodeLLDB to your newly built <code>lldb-dap.exe<\/code> or <code>liblldb.dll<\/code> respectively. If you're on Windows, make sure to compile for MSVC otherwise CodeLLDB won't be able to interface with <code>liblldb<\/code> properly.<\/p>"},{"title":"So you want better debug info?","published":"2025-02-14T00:00:00+00:00","updated":"2025-02-14T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/so-you-want-better-debug-info\/"}},"id":"https:\/\/walnut356.github.io\/posts\/so-you-want-better-debug-info\/","summary":"<p>Let me start with an emphatic <strong>\"me too\"<\/strong>.<\/p>\n<p>I've put many of my side projects on hold because recent events have resulted in, what I consider to be, an unacceptable degredation of the debugging experience. It's a bit hard to focus on whatever I'm doing when I have to fight to figure out what's in a <code>Vec<\/code>. One of the great things about programming is that we're the ones who make our own tools; we don't have to just blindly accept mediocrity.<\/p>"},{"title":"TwoVec: A Very Silly Container","published":"2024-10-18T00:00:00+00:00","updated":"2024-10-18T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/twovec-a-very-silly-container\/"}},"id":"https:\/\/walnut356.github.io\/posts\/twovec-a-very-silly-container\/","summary":"<p>Lets say you want to store two different types of objects in 1 container. Simple right? Just slap those puppies in a tuple and you're good to go:<\/p>\n<pre class=\"giallo\" style=\"color: #ABB2BF; background-color: #282C34;\"><code data-lang=\"rust\"><span class=\"giallo-l\"><span style=\"color: #C678DD;\">let<\/span><span style=\"color: #E06C75;\"> list<\/span><span>:<\/span><span style=\"color: #E5C07B;\"> Vec<\/span><span>&lt;(<\/span><span style=\"color: #E5C07B;\">u8<\/span><span>,<\/span><span style=\"color: #E5C07B;\"> f32<\/span><span>)&gt;<\/span><span style=\"color: #56B6C2;\"> =<\/span><span style=\"color: #61AFEF;\"> vec!<\/span><span>[(<\/span><span style=\"color: #D19A66;\">255<\/span><span>,<\/span><span style=\"color: #D19A66;\"> 20.0<\/span><span>), (<\/span><span style=\"color: #D19A66;\">10<\/span><span>,<\/span><span style=\"color: #D19A66;\"> 37.0<\/span><span>)];<\/span><\/span><\/code><\/pre>\n<p>But what if you wanted to include elements of two different types in <em>arbitrary orders<\/em>? Thankfully, there's sum types for that:<\/p>\n<pre class=\"giallo\" style=\"color: #ABB2BF; background-color: #282C34;\"><code data-lang=\"rust\"><span class=\"giallo-l\"><span style=\"color: #C678DD;\">pub enum<\/span><span style=\"color: #E5C07B;\"> Val<\/span><span> {<\/span><\/span>\n<span class=\"giallo-l\"><span style=\"color: #61AFEF;\">    A<\/span><span>(<\/span><span style=\"color: #E5C07B;\">u8<\/span><span>),<\/span><\/span>\n<span class=\"giallo-l\"><span style=\"color: #61AFEF;\">    B<\/span><span>(<\/span><span style=\"color: #E5C07B;\">f32<\/span><span>),<\/span><\/span>\n<span class=\"giallo-l\"><span>}<\/span><\/span>\n<span class=\"giallo-l\"><\/span>\n<span class=\"giallo-l\"><span>... {<\/span><\/span>\n<span class=\"giallo-l\"><span style=\"color: #C678DD;\">    let<\/span><span style=\"color: #E06C75;\"> list<\/span><span style=\"color: #56B6C2;\"> =<\/span><span style=\"color: #61AFEF;\"> vec!<\/span><span>[<\/span><span style=\"color: #E5C07B;\">Val<\/span><span>::<\/span><span style=\"color: #61AFEF;\">A<\/span><span>(<\/span><span style=\"color: #D19A66;\">255<\/span><span>),<\/span><span style=\"color: #E5C07B;\"> Val<\/span><span>::<\/span><span style=\"color: #61AFEF;\">B<\/span><span>(<\/span><span style=\"color: #D19A66;\">20.0<\/span><span>),<\/span><span style=\"color: #E5C07B;\"> Val<\/span><span>::<\/span><span style=\"color: #61AFEF;\">B<\/span><span>(<\/span><span style=\"color: #D19A66;\">37.0<\/span><span>),<\/span><span style=\"color: #E5C07B;\"> Val<\/span><span>::<\/span><span style=\"color: #61AFEF;\">A<\/span><span>(<\/span><span style=\"color: #D19A66;\">10<\/span><span>)];<\/span><\/span>\n<span class=\"giallo-l\"><span>}<\/span><\/span><\/code><\/pre>\n<p>One small problem. That's <em>wasteful<\/em>.<\/p>"},{"title":"Why is language documentation still so terrible?","published":"2024-09-12T00:00:00+00:00","updated":"2024-09-12T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/language-documentation\/"}},"id":"https:\/\/walnut356.github.io\/posts\/language-documentation\/","summary":"<p>Seriously, is there a good reason for this? I feel like I'm going crazy because almost every language doc I've looked at is legitimately awful in a bunch of obvious ways. It's not uncommon to see third party libraries updated by a single person that are better structured, more thorough, with better layouts than the official documentation upheld by the language team itself.<\/p>"},{"title":"Bypassing the borrow checker - do ref -> ptr -> ref partial borrows cause UB?","published":"2024-08-09T00:00:00+00:00","updated":"2024-08-09T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/partial-borrow-pointer-ub\/"}},"id":"https:\/\/walnut356.github.io\/posts\/partial-borrow-pointer-ub\/","summary":"<p>Partial borrows across function boundaries don't really work in Rust. Unfortunately, that's kind of a major issue. There are workarounds, some are outlined <a rel=\"noopener external\" target=\"_blank\" href=\"https:\/\/smallcultfollowing.com\/babysteps\/blog\/2018\/11\/01\/after-nll-interprocedural-conflicts\/\">here<\/a>, but all of them come with pretty major drawbacks.<\/p>"},{"title":"Simulating Starcraft Part 2 - Data Wrangling","published":"2024-06-02T00:00:00+00:00","updated":"2024-06-02T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/simulating-starcraft-p2\/"}},"id":"https:\/\/walnut356.github.io\/posts\/simulating-starcraft-p2\/","summary":"<p>Oh how naive I was when I thought I'd be moving on to pathfinding and abilities. I had hoped some of the game's mechanics would function better in isolation, so I could gradually add complexity on top of the tracer bullet in a modular way. Unfortunately, that doesn't seem possible without a huge refactoring burden every time I add the next layer. It'll be more worth my time to properly architect it right now, and build it from the ground up with all of the systems it'll need.<\/p>"},{"title":"Simulating Starcraft Part 1 - Tracer Bullet","published":"2024-05-15T00:00:00+00:00","updated":"2024-05-15T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/simulating-starcraft-p1\/"}},"id":"https:\/\/walnut356.github.io\/posts\/simulating-starcraft-p1\/","summary":"<p>A while back, I made a <a rel=\"noopener external\" target=\"_blank\" href=\"https:\/\/github.com\/Walnut356\/SC2-Upgrade-Calculator\">small application<\/a> meant to demonstrate some important principles about RTS design, namely that unit stats in a vacuum can be very misleading. As a quick example, stalkers have ~9.7 dps on paper. When fighting marines though, their effective DPS drops to ~8.4 (8.2 with combat shields) due to overkill. That's about the same DPS as a sentry. Unfortunately, there's only so much info that can be extracted from a Time To Kill calculation between two units.<\/p>"},{"title":"The space time complexity tradeoff","published":"2024-03-09T00:00:00+00:00","updated":"2024-03-09T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/space-time-complexity-tradeoff\/"}},"id":"https:\/\/walnut356.github.io\/posts\/space-time-complexity-tradeoff\/","summary":"<p>I encountered a neat example recently while solving <a rel=\"noopener external\" target=\"_blank\" href=\"https:\/\/adventofcode.com\/2015\/day\/6\">Advent of Code 2015, day 6<\/a>. The problem can be boiled down to \"There is a 2D array of values. Given a range and instruction, apply the instruction to all values in that range. How many values are 'on' at the end?\". There are only 2 possible states for each value: on and off, and only 3 possible instructions: on, off, and toggle. I won't focus too much on parsing the input or the structure of the algorithm here, I just want to investigate the hot loop which applies the instruction to each value.<\/p>"},{"title":"Can you estimate playtime from replay folder size?","published":"2024-01-25T00:00:00+00:00","updated":"2024-01-25T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/estimate-playtime\/"}},"id":"https:\/\/walnut356.github.io\/posts\/estimate-playtime\/","summary":"<p>I've seen this question come up a few times on r\/ssbm and while I've given hand-wavey answers before, I find myself in a good place to answer more rigorously now. We can break this question down to more basic ones: \"how many bytes of replay data correspond to a single frame of gameplay?\" and \"how many bytes in the replay are unrelated to frames?\". From there, we can estimate a duration by simply translating the 16.667ms per frame to minutes and seconds.<\/p>"},{"title":"Syntax Test","published":"2024-01-01T00:00:00+00:00","updated":"2024-01-01T00:00:00+00:00","author":{"name":"\n            \n              Walnut356\n            \n          "},"link":{"@attributes":{"rel":"alternate","type":"text\/html","href":"https:\/\/walnut356.github.io\/posts\/syntax-test\/"}},"id":"https:\/\/walnut356.github.io\/posts\/syntax-test\/","summary":"<p>I write my own sublime-syntax files for the syntax highlighting on this site, this page is meant for testing edge cases.<\/p>"}]}