<?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="https://gingerdeity.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://gingerdeity.github.io/" rel="alternate" type="text/html" /><updated>2026-04-28T21:36:02-04:00</updated><id>https://gingerdeity.github.io/feed.xml</id><title type="html">Atreyu McLewin</title><subtitle>Atreyu McLewin&apos;s portfolio and website!</subtitle><author><name>Atreyu McLewin</name></author><entry><title type="html">PICO-8 Experiments</title><link href="https://gingerdeity.github.io/blog/pico8/" rel="alternate" type="text/html" title="PICO-8 Experiments" /><published>2026-04-28T00:00:00-04:00</published><updated>2026-04-28T00:00:00-04:00</updated><id>https://gingerdeity.github.io/blog/pico8</id><content type="html" xml:base="https://gingerdeity.github.io/blog/pico8/"><![CDATA[<p>Hey all, I know it’s been a while (about a month I think) since my last post, but honestly felt that I needed a break from it all to process a few things. I think I was burning myself out pretty hard with the rapid posts and the aim of such high quality for each one. I’ve also been going through a bit of an identity crisis lately, and wanted to take some time to reflect on that.</p>

<p>However, my time hasn’t been completely void of programming, and I’ve since tried learning the PICO-8 game engine to get my inspiration back up! I really love it so far, since it’s all about limits and making the most with a very limited toolset. Hell, you’re only allowed 8kb for all your code! I’ve followed a few tutorials so far, mostly geared towards top-down adventures. I’ve got three different downloads of both the raw lua scripts and the pico 8 cartridges:</p>

<h2 id="downloads">Downloads</h2>
<p><strong>Lua Scripts</strong></p>
<ul>
  <li><a href="/assets/downloads/adventure.lua">Adventure Game</a></li>
  <li><a href="/assets/downloads/zelda.lua">Zelda Game</a></li>
  <li><a href="/assets/downloads/test.lua">Test Game</a></li>
</ul>

<p><strong>PICO-8 Cartridges</strong></p>
<ul>
  <li><a href="/assets/downloads/adventure2.p8">Adventure Game</a></li>
  <li><a href="/assets/downloads/zelda.p8">Zelda Game</a></li>
  <li><a href="/assets/downloads/test.p8">Test Game</a></li>
</ul>

<p>I’d say what I’m most proud of so far is the adventure game one! I love the tiny art and would love to combine zelda movement with its small scale. I’m also currently investigating map tiles vs sprites in PICO-8 and would love to find/create my own engine for animated tiles if needed. That’s all for today, see ya around!</p>

<p style="text-align:center;">
  <img src="/assets/posts/2026-28-04/pico8.png" style="max-width:600px;" />
</p>

<blockquote>
  <p>“Hate is a place where a man who can’t stand sadness goes.”
<cite><a href="https://www.goodreads.com/quotes/130648-hate-is-a-place-where-a-man-who-can-t-stand"> Miura Kentaro</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="gamedev" /><category term="pico8" /><summary type="html"><![CDATA[A venture into using a new game engine!]]></summary></entry><entry><title type="html">Rhythm Fighting Game</title><link href="https://gingerdeity.github.io/blog/rhythmfighting/" rel="alternate" type="text/html" title="Rhythm Fighting Game" /><published>2026-03-24T00:00:00-04:00</published><updated>2026-03-24T00:00:00-04:00</updated><id>https://gingerdeity.github.io/blog/rhythmfighting</id><content type="html" xml:base="https://gingerdeity.github.io/blog/rhythmfighting/"><![CDATA[<p>This post is really more a spitball of ideas I’ve had for a dream fighting game for years now. But basically…</p>

<h2 id="fighting-to-the-beat">Fighting to the Beat</h2>
<p>There’s a really good <a href="https://www.youtube.com/watch?v=Z1PCtIaM_GQ">video essay about Jackie Chan</a> that talked about how his fights have a certain rhythm to them. How each hit happens on a specific beat, and each hit creates a sort of melody. As someone who’s also been obsessed with martial arts and fighting technique lately, I really like that idea.</p>

<p>I would love to have a fighting game where you are given an incentivize to time your hits to the background music! Imagine a game where you could do combos and high-stake fights like in those martial arts movies! There could be different fighters and stages for different genres of music, like:</p>

<p>Hip-Hop, Rock &amp; Roll, Phonk, Bebop, Rap, etc, etc</p>

<p>You could have it so everytime you perform 2 or more hits to the beat in the background, the more power the hit has, or the less lag behind a move, giving you more of an opportunity to perform a move on the next beat. Then, the music could get faster and faster, until you’d need TAS-level inputs to keep a combo going!</p>

<p>Of course, there’d also be a chance for the other player to counter the attack by dodging or blocking to the beat also. It’s a very complex concept, but I feel that, if done well, could be incredibly addicting and fun to pull off!</p>

<p>There could be moves or actions that you need to do inputs for on specific beats too… that’d be a <strong>great</strong> way to make the player feel truly in control. It could be a really good balance between the intuitiveness of Smash Bros. and the combos of Street Fighter and Soul Caliber!!</p>

<h2 id="community-mods">Community Mods</h2>
<p>A great part about a game like this would be that rhythm games like DDR have extensive histories of mods. It could be really easy for a community of modders to add their own stages/songs to the game, and you could suddenly have your characters fighting to your favorite song. Having characters fight to Tequila would be hilarious</p>

<h2 id="character-stories">Character Stories</h2>
<p>In an interview about Super Smash Bros. Melee, Masahiro Sakurai (the director and creator of Smash Bros. and Kirby) talked about how he went about designing the characters Marth and Roy, the two swordsmen characters. He talked about how, since Marth was the more experienced fighter, he wanted Marth to be elegant and quick. Meanwhile, Roy, the less experienced fighter, would be a bit more brutish but fiery and powerful. Refined and quick versus unrefined but powerful…</p>

<p>Combining this with how minimal a lot of single-player modes in fighting games are usually lack-luster, I feel like this is a great opportunity. What if you could unlock different versions of characters through the story mode? All characters at the start of the game are in their ‘novice’ state, but still perfectly usable! However, the more of the story-mode you play, the more refined and different the characters could get in terms of movesets.</p>

<p>I don’t know, this is a pretty abstract idea. But I just love the idea of getting to see different ‘flavors’ of your characters in an actually fun single-player mode. The story could be interweaving between the entire cast, and there’d be all sorts of endings!</p>

<h2 id="minigames">Minigames</h2>
<p>Another benefit to having rhythm play such a huge role in a fighting game? Minigame ideas are <em>right</em> there!</p>

<p>1) A reaction-timing training game akin to <a href="https://www.youtube.com/watch?v=JErtGVTioPc">Rhythm Fever’s Karate Man minigame</a></p>

<p>2) Challenge mode, where you can only do hits or attacks on certain beats to a song</p>

<p>3) A ‘battle of the bands’ mode where characters fight purely through band rivalries, that’d be really fun for some 4-player  action</p>

<p>4) Like the <a href="https://www.youtube.com/watch?v=DVdvUGWQJsM">beat on time challenge</a>, but for certain buttons/combos</p>

<p>5) The <a href="https://www.youtube.com/shorts/_cF5ZEY1wPE">Whitney Houston challenge</a> as a game</p>

<p>6) Reaction test, just see if you can win against the opponent by pressing a button first</p>

<p>That’s just a few simple ones, but you could probably think of several more</p>

<h2 id="customization">Customization</h2>
<p>This one’s simple, I want the ability to map controller inputs and to have the frame buffer be customizable too. The larger your frame buffer, the more gracious for fighting, but will also leave you unable to continue combos that get to certain low frame-windows!</p>

<h2 id="final-thoughts">Final Thoughts</h2>
<p>I just wanted to write a post about an idea that’s been in my heart for years. Who knows? Maybe some day it’ll come true, or the right people will see this post and think “i’d love to help make this!” Who knows where life leads you?</p>

<p>I’ve also been very focused on my fitness and health lately, just this morning I was able to do 10 pull ups! I feel myself getting stronger again, and that feels great. Also, even though it’s only been a week, I’ve already completely finished the original DragonBall manga!! It turns out I’m a huge manga fan, which makes sense when I think about how obsessed with Calvin and Hobbes I was as a kid. It’s basically the same thing, but with cooler pictures and panels… I’m surprised with how long it’s taken me to get into it.</p>

<p>Now I’m reading Vagabond, and have also been studying Buddhism lately. Vagabond is… truly something else, if you haven’t read it yet.</p>

<p style="text-align:center;">
  <img src="/assets/posts/2026-24-03/vagabond.png" style="max-width:600px;" />
</p>

<p>That’s all for today, until next time!</p>

<blockquote>
  <p>“Invincible… it’s merely a word. To be ‘invincible.’ The more you think about it… the more you squint your eyes in desperation to see… the more obscured the answer becomes. If something’s too obscure to see… the try closing your eyes. Well…? Do you see how infinite you are?”
<cite><a href="https://www.goodreads.com/author/quotes/147221.Takehiko_Inoue">Takehiko Inoue</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="gamedev" /><category term="godot" /><summary type="html"><![CDATA[A spitball of ideas for a fighting game long dormant in my imagination]]></summary></entry><entry><title type="html">In-Progress Updates</title><link href="https://gingerdeity.github.io/blog/js101/" rel="alternate" type="text/html" title="In-Progress Updates" /><published>2026-03-17T00:00:00-04:00</published><updated>2026-03-17T00:00:00-04:00</updated><id>https://gingerdeity.github.io/blog/js101</id><content type="html" xml:base="https://gingerdeity.github.io/blog/js101/"><![CDATA[<p>Today’s post is going to be a lot smaller since I’ve got some family plans for St. Patty’s Day (cornbeef and Guinness, yum!) and haven’t had as much time to work on projects this past week. So, I’m just going to highlight some projects that are in progress besides the Tetris NES game!</p>

<h2 id="frogrunner">FrogRunner</h2>
<p>I’ll be honest, I’ve gotten very tired of trying to get the springy-rope physics to work, so I’ve briefly switched focus to keeping my Blender skills fresh. I opened up Blender and quickly started work on a model for the frog here:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-17-03/frog_model.png" style="max-width:600px;" />
</p>

<p>The reference art was actually made by my brother. I like it, though the lines in the picture often overlap with the gridlines in Blender, and that’s been a bit tricky. To make sure I don’t burn out on this project, I’ll be focusing more on sound design and graphics for the time being.</p>

<h2 id="javascript">JavaScript</h2>
<p>Oddly enough, JavaScript and web-dev were something we weirdly skipped over in college. I took one class where (despite being advertised as a beginner’s course) we had to do 20+ hours of LinkedIn courses to learn JS, HTML, and CSS so that we could even do the first homework. For homework 2, I think the class spent an average of 12 hours on it. I was an officer of a club, biking 5 miles a day to and from campus, working 2 jobs, and doing 4 other tough classes… I dropped that class after nearly 2 months.</p>

<p>That was the first and last time I was able to do web-dev in college. Keep in mind that I was a transfer student, so I had only been learning coding for about a year at that point. Our college required us to have an Associate’s degree in engineering, not computer science… I still think that was a really strange choice.</p>

<p>Anyways, all that to say I’ve been practicing on and off with JavaScript, working my way through the <a href="https://eloquentjavascript.net/index.html">Eloquent JS book by Marijn Haverbeke</a> and doing all the exercises. Last I checked, I was working through chapter 4 and data structures. But… It’s been a few weeks since then, so I’ll probably have to skim some of the chapters to get the rust off. Here’s an image of my coding environment:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-17-03/js101.png" style="max-width:600px;" />
</p>

<p>Honestly, what really surprises me about JS so far is how much it treats functions like <em>values</em>. In so many other languages, you’re taught that “code is comprised of values and functions that modify those values”, but that doesn’t really exist here. <em>Closures</em> are also crazy interesting, and having to train my brain to think of functions as containing their own ‘environment’ is an interesting exercise.</p>

<p>My hope is to have a simple REST API project done within a month or so. I feel like that’d be a great start!</p>

<h2 id="final-thoughts">Final Thoughts</h2>
<p>Some weeks, you just can’t get as much done. Stuff slips through your fingers, you forget things, or you’re just a lot more tired than you normally are. What fitness has been teaching me is that when days like that come, you just have to accept it. Honestly, accepting and letting go are two lessons I really need to get better at. I’m a very controlling person, and like having all my ducks in a row.</p>

<p>Having weeks like this, where I didn’t make much project progress, and have been feeling a lot more tired and depressed than normal, is important. You can’t operate on the assumption you’ll be feeling 100% all the time, even if there’s no good reason for you to feel otherwise. We’re humans, not machines. Sometimes, all you can do is get the rest/reset you need, then go back and try to be better!</p>

<p>Reading the Dragon Ball manga has been a really nice reminder about this. Every time that kid Goku gets his butt handed to him, he sees it as an opportunity to get better. There’s no hubris or ego involved, just understanding and optimism. I get really in my head sometimes, and this story has been great at dealing with that.</p>

<p>Plus, you get to see really cute drawings like this one (RIP Toriyama!)</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-17-03/goku_kid.png" style="max-width:600px;" />
</p>

<p>Oh, I also rewatched The Neverending Story last night. There’s really something about watching your namesake with family that helps get your spirits up. Until next time, stay hopeful!</p>

<blockquote>
  <p>“Only the right name gives beings and things their reality. A wrong name makes everything unreal. That’s what lies do.”
<cite><a href="https://www.goodreads.com/work/quotes/1122661-die-unendliche-geschichte"> Michael Ende</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="gamedev" /><category term="javascript" /><category term="webdev" /><summary type="html"><![CDATA[A brief update on certain projects]]></summary></entry><entry><title type="html">Tetris NES, Deep Dive #3</title><link href="https://gingerdeity.github.io/blog/tetrisnes3/" rel="alternate" type="text/html" title="Tetris NES, Deep Dive #3" /><published>2026-03-10T00:00:00-04:00</published><updated>2026-03-10T00:00:00-04:00</updated><id>https://gingerdeity.github.io/blog/tetrisnes3</id><content type="html" xml:base="https://gingerdeity.github.io/blog/tetrisnes3/"><![CDATA[<h2 id="the-story-so-far">The Story so Far…</h2>
<p>Last Antholog, I switched to using a pre-existing decompilation, rather than trying to make my own, and was able to successfully start removing unused game data and adding new piece rotations! Amazingly, by using my old findings and this new decompilation, in two weeks, I was able to essentially completely replicate the final state of the school project that took me a couple of months.</p>

<p>However, that meant also replicating the same errors. In particular, the size of the new table needed for these pieces was &gt;256 bytes, which didn’t hold well for an 8-bit computer! Since the NES can only hold a maximum value of 256, that meant the final pieces in the table (for me, the O and I pieces) were too far to be able to get their data. Any time the game tried to grab them, the engine recognized it as an invalid piece, and that resulted in the level ending immediately.</p>

<p>We also saw that the statistics for the game weren’t being updated correctly, as you can see below:</p>
<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-03-03/tetris_updated1.mp4" type="video/mp4" />
</video>

<h2 id="whats-new">What’s New?</h2>
<p>Since last week, I’ve been able to fix the statistics window! After snooping around the code, I was able to find an <code class="language-plaintext highlighter-rouge">incrementPieceStat</code> function and a <code class="language-plaintext highlighter-rouge">statsByType</code> memory address. Here’s a screenshot of an unmodified Tetris game, and a corresponding memory viewer:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-10-03/tetris_statsbytype.png" style="max-width:600px;" />
</p>

<p>Highlighted in the window to the right is the <code class="language-plaintext highlighter-rouge">statsByType</code> data, which I’ve also included here:</p>

<p><code class="language-plaintext highlighter-rouge">01 00 01 00 01 00 03 00 04 00 03 00 01 00 00 00</code></p>

<p>The correlation becomes crystal clear when you look at the game screenshot. <code class="language-plaintext highlighter-rouge">statsByType</code> shows the number of T, J, Z, O, S, L, and I pieces, the same order from top-to-bottom in that statistics window… the same order as the ID of the pieces in the game’s original code.</p>

<h2 id="fixing-it-block-by-block">Fixing it, Block-By-Block</h2>
<p>At first, I thought maybe my new pieces and reordering of the piece IDs weren’t being properly integrated with <code class="language-plaintext highlighter-rouge">statsByType</code>. But after doing some gameplay and observing the data, that clearly wasn’t the case.</p>

<p>After confirming the new IDs were being correctly integrated with <code class="language-plaintext highlighter-rouge">statsByType</code>, I realized the problem was the graphics. In fact, if you watch the video above, the numbers <em>are being updated correctly</em>, but the graphics on the statistics sheet weren’t in the right place. Again, the statistics window has the pieces ordered based on the piece IDs in the original code.</p>

<p>The original code orders the piece IDs like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tPiece = $00
jPiece = $01
zPiece = $02
oPiece = $03
sPiece = $04
lPiece = $05
iPiece = $06
</code></pre></div></div>

<p>But our new code orders them like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tPiece = $00
jPiece = $01
lPiece = $02
zPiece = $03
sPiece = $04
iPiece = $05
oPiece = $06
</code></pre></div></div>

<p>The new organization is far superior in my eyes since mirror pieces are right next to each other (J next to L, Z next to S), and the misalignments in <code class="language-plaintext highlighter-rouge">orientationTable</code> caused by the O block using only 1 rotation instead of 4 rotations like all other blocks are fixed by having it at the very end. For these reasons, I didn’t want to revert the piece IDs as a way to make the statistics window work.</p>

<p>Then, I thought that maybe changing the locations of the sprites in the data itself would fix it. You can see the original data here:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-10-03/tetris_yychr.png" style="max-width:600px;" />
</p>

<p>I thought that moving those pieces around would fix it, but I found that it only caused other graphical issues. After that, I looked through the code again for anything that resembled sprite data. Then, I found a <code class="language-plaintext highlighter-rouge">pieceToPpuStatAddr</code> table:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pieceToPpuStatAddr:
    .dbyt   $2186,$21C6,$2206,$2246
    .dbyt   $2286,$22C6,$2306
</code></pre></div></div>

<p>The name told me this was used to convert piece IDs to PPU (picture-processing unit, aka graphics) memory locations. So, I tried just modifying it according to my new piece IDs, and… that’s all it took! Now the score works perfectly!</p>

<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-10-03/tetris_fixed_stats.mp4" type="video/mp4" />
</video>

<h2 id="whats-next">What’s Next?</h2>
<p>Now that the statistics are being updated properly, we need to have access to all our blocks. After all, it’s hard to keep calling this a Tetris project when we can’t even get a Tetris! Adding in the I and O blocks, using the <code class="language-plaintext highlighter-rouge">orientationTable</code> modifications I talked about last week, will be the next logical step.</p>

<p>After that, this project will technically be finished! Granted, I could try and add the wall-kicks that my school partner couldn’t, but that sounds a lot more intense and time-consuming than I’d be willing to endure. At most, I might just scour the internet for other ROM-hacks of this game that already do wall-kicks and just borrow from them.</p>

<p>I will say, the idea of a fully revamped Tetris ROM does sound exciting… modern rotations, wall-kicks, hard-drops, saving pieces, T-spins, ghost pieces, and adding back in the most iconic Tetris theme. Finding ROM-Hacks that do each of those things and adding them together like a Frankenstein monster could be exciting. Besides, <em>Ultimate Tetris</em> does have a nice ring to it…</p>

<h2 id="final-thoughts">Final Thoughts</h2>
<p>This was a much shorter post than the last few, which is quite refreshing. Sometimes, these posts take up 12 to 14 hours in a single day to finish certain parts of a project, then to collect all the data and screenshots and videos, then to start writing, and doing final spellchecks and revisions, before finally posting online. I also pride myself on not using any AI like ChatGPT or Gemini to write any of this. The only thing I typically use is Grammarly for spell-checking and restructuring certain sentences.</p>

<p>Still, both this project and the site have been very rewarding so far! Whether the next post will focus on this project, I’m not certain yet. This site is still pretty new, and I haven’t really worked out a proper uploading schedule yet. It’s really just been a ‘go with the flow’ kind of project for now, to help ensure I don’t burn out or box myself in too tightly. As for <em>when</em> will I start scheduling upload ideas ahead of time? Uhhhhhhhhhhhhhhhhhhh</p>

<p>In other news, I recently finished reading the DragonBall Z manga! My first time ‘finishing’ DragonBall Z was the Abridged series on YouTube, and I always wanted to watch the original. But I thought the original had wayyy too much filler, and didn’t like all the changes that Kai made. So, I decided to start by just reading the manga! I ATE that thing up. I think I read every issue in less than 3 weeks? Now I’m trying out the original DragonBall manga.</p>

<p>I used to read a lot more, so it’s been nice getting back into the habit. It’s been replacing that old habit of binging reels and shorts like tic-tacs, so for that I’m very grateful. Anyways, until next time!</p>

<blockquote>
  <p>“Grown-ups never understand anything by themselves, and it is tiresome for children to be always and forever explaining things to them.” 
<cite><a href="https://www.goodreads.com/work/quotes/2180358-le-petit-prince"> Antoine de Saint-Exupéry</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="romhack" /><category term="game dev" /><category term="assembly" /><summary type="html"><![CDATA[The one simple fix for updating the statistics window!]]></summary></entry><entry><title type="html">Tetris NES, Deep Dive #2</title><link href="https://gingerdeity.github.io/blog/tetrisnes2/" rel="alternate" type="text/html" title="Tetris NES, Deep Dive #2" /><published>2026-03-03T00:00:00-05:00</published><updated>2026-03-03T00:00:00-05:00</updated><id>https://gingerdeity.github.io/blog/tetrisnes2</id><content type="html" xml:base="https://gingerdeity.github.io/blog/tetrisnes2/"><![CDATA[<h2 id="the-story-so-far">The Story so Far…</h2>
<p>Since my last post on this project, I’ve made <em>lots</em> of progress in my Tetris ROM-Hack! Last post, I talked about my discoveries and studies involving the NES-emulator config file format, and how I greatly improved mine. I also talked about the difficulties with the original school project, mainly being that we had to translate our own decompilation of the ROM, which resulted in a highly volatile assembly ROM. It was so volatile, in fact, that adding any new code or data into the existing code would typically result in a green screen of death. We believed this to be the cause of important game vectors being overwritten, but couldn’t tell for sure:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-10-02/green_screen_of_death.png" style="max-width:600px;" />
</p>

<h2 id="how-am-i-doing-this-rom-hack">How am I doing this ROM-Hack?</h2>
<p>In my last post, I mentioned how I was still deciding between using an already decompiled version of the game, rather than making my own. Since then, I messed around with an <a href="https://github.com/CelestialAmber/TetrisNESDisasm">already decompiled Tetris ROM</a>, and have quickly decided to pursue finishing the original project with this decompilation!</p>

<p>It is… <strong><em>FAR</em></strong> easier to work with. For starters, the creators of this decomp were able to divide the files into sections like RAM, constants, tilesets, and the main code. On top of that, variables are all properly named, and there are comments everywhere. Reading and understanding the code has never been easier! On top of that, they’ve even gone the extra effort and labelled the code and data that is unreferenced and unused.</p>

<p>I’m also able to justify using this decomp since the overall aim of the project has changed. See, the original project was a school assignment, meant to test our abilities working with decompilations. Now, I’m far more interested in just getting a ROM hack to work! It’s different goals, which I think justifies different methodologies.</p>

<h2 id="new-discoveries">New Discoveries?</h2>
<p>This decomp was able to help me figure out an even more likely cause for that constant green screen of death. Turns out, our original assumption that code or data was being offset might’ve been completely correct. Check this out, in the decomp, they include an OAM content lookup table, basically a table that stores certain information for sprites. However, some of the entries in that table are unused, like so:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oamContentLookup:
        .addr   sprite00LevelSelectCursor
        .addr   sprite01GameTypeCursor
        .addr   sprite02Blank
        ...
        .addr   sprite13LPieceOffset
        ...
...
; Unused, but referenced from unreferenced_orientationToSpriteTable
sprite13LPieceOffset:
        .byte   $08,$7C,$02,$F8,$08,$7C,$02,$00
        .byte   $08,$7C,$02,$08,$10,$7C,$02,$F8
        .byte   $FF
</code></pre></div></div>

<p>Deleting the <code class="language-plaintext highlighter-rouge">sprite13LPieceOffset</code> data and its entry in the OAM content lookup table would help increase space and remove unnecessary code and data. So, I deleted it and… nothing seemed to change in the game. I decided to keep continuing with the deletions, one at a time, still not seeing any glitches in the game. Eventually, after a bit more clean-up, the green screen of death came back!</p>

<p>I realized that, while the entry itself wasn’t being used, there was still code that was depending on the table being a certain size, or certain entries being offset by a certain amount. When I went back, I replaced all the entries in the table I had deleted with the <code class="language-plaintext highlighter-rouge">.addr sprite02Blank</code> entry. This fixed everything!</p>

<p>My theory is that when we were removing or adding certain lines of code or data into the middle of preexisting code, our assembler was letting that offset ripple throughout the rest of the code! Tables were no longer in the exact address that the code was expecting, etc, etc. I now believe that what happened with my OAM deletions is what likely happened back then, except propagated throughout the entire code.</p>

<h2 id="progress-made">Progress Made</h2>
<p>I was able to remove at least 220 bytes of unused OAM content, and another 964 bytes from an unused sprite-staging function, resulting in 1,184 bytes of saved memory! Now, that might sound <em>incredibly</em> minimal (because, I mean… it is…), but remember that the final Tetris ROM itself is 49,168 bytes. Using that as a metric, the amount I was able to remove took up 2.41% of the game’s final space!</p>

<p>Again, these games are <em>tiny</em>; it’s a miracle we could make anything with such limited resources. Imagine going back in time to work on this game and telling the developers that you removed that much code. I like to imagine they’d be very pleased :)</p>

<p>Anyway, what else has been done? Well, after experimenting with the decomp by removing unused code and data, I was able to quickly add <strong><em>the missing rotation states</em></strong>! Yep, the original project’s dream has already been added! Here’s the video:</p>

<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-03-03/tetris_updated1.mp4" type="video/mp4" />
</video>

<p>So… I may have been a bit too quick to say that the project goal has been met already, since the game seems to crash out of nowhere… but we’ve still made progress!</p>

<p>You can see it clearly if you look at the S and Z blocks. For the S-block, the original game had it flipping between just two states, but newer games make sure it rotates around a center position. If you look at the video, you’ll see that’s true for the Z and S blocks now! They shift and rotate in ways the original game didn’t allow.</p>

<p><strong>Old S-Block:</strong></p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-03-03/tetris_s_old.png" style="max-width:600px;" />
</p>

<p><strong>Modern S-Block:</strong></p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-03-03/tetris_s_modern.png" style="max-width:600px;" />
</p>

<p>However, as you clearly saw, the game crashed once the O-block appeared, and the statistics for the blocks weren’t being updated correctly either. What went wrong?? To answer that, we’ll need to understand how Tetris blocks are processed.</p>

<h2 id="the-orientation-table">The Orientation Table</h2>
<p>The code for Tetris uses an <em>orientation table</em> to tell the game how to display each block rotation to the screen. Here’s what it looks like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>orientationTable:
        ; y offset, tile ID, x offset per mino per orientation
        .byte    0, tile1,-1, 0, tile1, 0, 0, tile1, 1,-1, tile1, 0 ; $00 t up
        .byte   -1, tile1, 0, 0, tile1, 0, 0, tile1, 1, 1, tile1, 0 ; $01 t right
        .byte    0, tile1,-1, 0, tile1, 0, 0, tile1, 1, 1, tile1, 0 ; $02 t down (spawn)
        .byte   -1, tile1, 0, 0, tile1,-1, 0, tile1, 0, 1, tile1, 0 ; $03 t left
        
        ...
        
        ; Hidden orientation used during line clear animation and game over curtain
        .byte    0, tileHidden, 0, 0, tileHidden, 0, 0, tileHidden, 0, 0, tileHidden, 0 ; $13
</code></pre></div></div>

<p>Each tetromino has 4 pieces, and each piece has 3 bytes allocated to it, telling the game its tile graphic to use, and its X and Y position in a grid. This slide I made for my school presentation does a great job of visualizing it:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-03-03/o_table_old.png" style="max-width:600px;" />
</p>

<p>The original orientation table is 240 bytes total. But, when we add the necessary information for the new blocks both in and outside the orientation table, our new orientation table is 312 bytes! Now remember, the NES is an 8-bit computer, meaning it only works in values of 1 byte at a time… meaning the largest value in an NES at any time is 255.</p>

<p>So, when our original table was less than 255 bytes, we could easily index into it as needed. But the moment we added indexes larger than 255, our game started to crash! And wouldn’t you know it? The way we’ve reordered the orientation table has our O and I blocks located just past the 255th index. This explains why the game crashed when we spawned in an O-block, and why it would also crash when we spawn in an I-block.</p>

<p>As for why the statistics on the side of the screen aren’t updating properly, I have yet to tackle that.</p>

<h2 id="the-solution">The Solution?</h2>
<p>As even a novice programmer could probably tell, the old table uses a lot of unnecessary space for storing the same tile bytes over and over again. So, I devised my own format for the table, as shown:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tiles:
    .byte tile1, tile3, tile2, tile2, tile3, tile1, tile1, tileHidden

orientationTable:
    .byte    0,-1, 0, 0, 0, 1,-1, 0 ; $00 t up
    .byte   -1, 0, 0, 0, 0, 1, 1, 0 ; $01 t right
    .byte    0,-1, 0, 0, 0, 1, 1, 0 ; $02 t down (spawn)
    .byte   -1, 0, 0,-1, 0, 0, 1, 0 ; $03 t left

    ...

    ; Hidden orientation used during line clear animation and game over curtain
    .byte    0, 0, 0, 0, 0, 0, 0, 0 ; $19
</code></pre></div></div>

<p>As you can probably already tell, the new table is way smaller, but get this! The table used in the original game uses:</p>

<p><code class="language-plaintext highlighter-rouge">(3 bytes per piece) * (4 pieces per orientation) * (20 orientations) = 240 bytes</code></p>

<p>And this new, optimized pair of tables would use:</p>

<p><code class="language-plaintext highlighter-rouge">(2 bytes per piece) * (4 pieces per orientation) * (26 orientations) + (8 tile bytes) = 216 bytes</code></p>

<p>That’s right, even though we’ve added in what are essentially another 6 brand new pieces/orientations, we’re actually <em>smaller</em> than the original game’s table if we use this new format!! Pretty amazing stuff if you ask me.</p>

<h2 id="whats-next">What’s Next?</h2>
<p>Simple. We just need to look through the code and change how the orientation table is being accessed. In my search, I found 10 references to the table across 4 functions. That means we’ll likely be needing to change the logic in those areas at least.</p>

<p>I’ve been fortunate enough that I haven’t had to really touch much assembly code so far, mostly just diagnosing, changing/adding bytes, and learning formats up to now. However, it looks like it’ll finally be time for me to get my hands dirty with the logic!</p>

<p>Also, here’s an old Python script from my school project I was able to get working that let me more easily visualize the table I was modifying :)</p>

<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-03-03/python_help.mp4" type="video/mp4" />
</video>

<h2 id="final-thoughts">Final Thoughts</h2>
<p>Honestly, this week was really good in terms of progress! With all these changes and advancements, I was able to essentially get back to where I last left the project in school. The road ahead is clear, and I’m looking forward to brushing up on my assembly! We’ll see what I can do in the meantime; it’ll likely be tougher to work on this now that I’ve recently started working for a start-up, which I’ll likely talk about at some point in the future. Oh well, until next time!</p>

<blockquote>
  <p>“He that breaks a thing to find out what it is has left the path of wisdom.” 
<cite><a href="https://www.goodreads.com/quotes/tag/gandalf">J.R.R. Tolkien</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="romhack" /><category term="game dev" /><category term="assembly" /><summary type="html"><![CDATA[The advancements made thus far in my Tetris NES romhack project, and what's next]]></summary></entry><entry><title type="html">Hustle Culture and Games</title><link href="https://gingerdeity.github.io/blog/sustainability/" rel="alternate" type="text/html" title="Hustle Culture and Games" /><published>2026-02-24T00:00:00-05:00</published><updated>2026-02-24T00:00:00-05:00</updated><id>https://gingerdeity.github.io/blog/sustainability</id><content type="html" xml:base="https://gingerdeity.github.io/blog/sustainability/"><![CDATA[<h2 id="disclaimer">Disclaimer</h2>
<p>This post is going to be a lot more personal and maybe a bit less polished than the typical one. While a lot of the issues I’ll be writing about in this do apply to the tech and programming world, this post isn’t really about anything directly related to tech or programming. Because of that, I was really contemplating whether or not to write about this subject, but remembered that one of the very first sentences in my About Me page was <em>“this website, above all, is meant to be a way to help tell you who I really am!”</em>. So, ironically, my posting only tech and programming stuff would’ve actually gone against the very principles I laid out for this Antholog. With that in mind, I hope you enjoy, and expect the occasional post to be a bit more personal.</p>

<h2 id="the-power-and-pain-of-games-and-gamification">The Power and Pain of Games and Gamification</h2>
<p>As I’ve likely said an obnoxious amount of times in this Antholog already, games are amazing. They transform their audience from passive spectators to active participants. Games are empowering in that way, letting you do more than just listen to the stories, but to shape them and interact with them. Games can tell you who you are and inspire you. Above all, games are fun, and the good ones are proper art.</p>

<p>But, for all the waxing poetics I can say about games, there is, like all things, that dark underbelly. The word gamify, to apply the principles of games to work, life, and hobbies, seems to have started circulating around the <a href="https://books.google.com/ngrams/graph?content=gamify&amp;year_start=1800&amp;year_end=2022&amp;corpus=en&amp;smoothing=3">early 2010s</a>. In principle, this can sound exciting and engaging, especially to people like me who already love games.</p>

<p>Unlike most of life, games have visible <em>statistics</em> and <em>objectives</em>. Even in games that don’t show a lot of numbers, like Zelda, you have a certain number of hearts that can increase throughout your quest. Games offer <em>definition</em> in a lot of areas that life just <em>doesn’t</em>. Some games display health or ammo, others show your relationship status with your friends and family, and others tell you your strength and stamina.</p>

<p>When you then look at how often life is frighteningly ambiguous, that philosophy of gamifying suddenly sounds a lot more appealing. Your life and all your problems are measurable and conquerable. But, for all its luster, this mindset seems to also come up often in what we refer to as <strong>hustle culture</strong>. There’s even similar wording between this culture and gaming, like <em>grinding</em> or <em>side-hustle</em>/<em>side-quest</em>.</p>

<p>For those who somehow aren’t aware, hustle culture is essentially the newest term for a lifestyle where your main focus is work and metrics. It’s characterized by ideas/goals like waking up at 4:00 am, going to the gym for 2 hours every day, only taking cold showers, getting a 6-figure salary, working 12 hours a day, and forgoing social interactions and events unless career-oriented. It’s filled with both fictional and nonfictional role models such as Bruce Wayne, Patrick Bateman, David Goggins, Gordon Ramsay, most high-paid athletes, etc. As in, the people who are the strongest, fastest, richest, most famous, and successful.</p>

<p>It’s the mentality of high motivation, profound discipline, and going all in until your goals are met. You live to work, and the work itself is the reward, no matter how grueling or tiresome. Hence, hustle culture’s mantras of “no pain, no gain” and “rise-and-grind”. You wake up, you work, you sleep (optional), you get hurt, you take pride in the pain. You bleed, you smile, you endure, you beg for more.</p>

<p>To most sane people, this sounds highly unrealistic, robotic, and depressing. However, I was not most sane people and even now, as a recovering perfectionist/overachiever, this can definitely <em>sound</em> exactly like what you’re looking for. You finally decide to get your life together, and never stop. And unfortunately, it feels pretty amazing, at least for a while. In the beginning, you’re waking up early, you’re doing your workouts, you’re eating exactly what you should be, you’re working up to 14 hours a day sometimes, you’re finally… progressing, leveling up. You’ve got your metrics, and you’re hitting almost every single one of them.</p>

<h2 id="no-all-pain-no-gain">No (All) Pain, No Gain!</h2>
<p>When I first moved after graduating from college, I swore to myself that I would become all that I thought I was meant to be, that I’d get out of my depressive mindset, and start really achieving and showing what I could do. Little more than a month after moving, I came up with the ultimate schedule.</p>

<p style="text-align:center;">
  <img src="/assets/posts/2026-24-02/schedule1.png" style="max-width:600px;" />
</p>
<p>(may require opening in its own tab to see properly)</p>

<p>I was waking up at 6:00 am, working out, showering, and then immediately working on networking and projects for at least 8 hours. I had screens off at exact minutes, I was performing at work, and I was following routines to a tee. Sure, I was a bit tired, but I felt like a brand new man.</p>

<p>That brand new man lasted about two weeks.</p>

<p>I started slipping up on certain routines, life got hectic in unexpected ways, and I was lying in my bed with no caffeine or screens yet awake and with a racing mind for hours on end. In retrospect, the pressure of not being able to hit my metrics, the fear of missing a time-block or meal, and the anxiety of not getting enough sleep, it wore me down.</p>

<p>On top of that, it made me frustrated. As you get more tired, you start slipping up, and the more I did, the more frustrated with myself I got. It was little things, like maybe not waking up until 7 am, or not being able to focus on work despite only working a typical 9-5, or maybe missing a workout. Little things like that, compounded with the 6-7 hours of sleep I was getting, all resulted in some pretty bad burnout that I’m only recently getting over.</p>

<p>I wish I could say that I’m one of the only people I know who have had this kind of problem, but unfortunately, it seems very common amongst people my age. It’s especially common in the world of programmers and tech. That ‘grindset’ and ‘move it or lose it’ attitude can drive nearly every project. Less resources, less time, less humanity, just to see if we can still hit those metrics.</p>

<h2 id="the-cost-of-perfection">The Cost of ‘Perfection’</h2>
<p>There’s a really great video I watched that talked about the lives of <a href="https://www.youtube.com/watch?v=1sGDIeldr-s">ancient Romans</a>, and argued that they’d likely see current hustle culture and be disgusted rather than impressed. There are two excerpts in that video that really stuck out,</p>

<blockquote>
  <p>“Work is the main event, leisure is the break. Romans saw it the exact opposite way. Their word for the ideal state of life was Odium… time dedicated to the things that make you human. Reading, writing, philosophy, gardening, friendship, and contemplation. To a Roman of the upper class, this was your real job. This was the purpose of being alive.”</p>
</blockquote>

<p>and</p>

<blockquote>
  <p>“They didn’t define leisure by the lack of work; they defined work by the lack of leisure. Work, or negotium, was the negative state; it was the annoying thing you had to do, the distraction that kept you from your actual life. “</p>
</blockquote>

<p>To be brutally honest, it’s quotes like this that make me want to cry, because it makes me look back on the last 10+ years of my life, and remember how as early as 12 years old it became filled with phrases like <em>“if I’m not perfect, or trying my best, I don’t think people would want to be my friend. I don’t think people would like me in their life,”</em> and <em>“Today you tried your best, it wasn’t enough, it’ll never be enough. That’s the beauty of it. Tomorrow, we try again, and maybe then we’ll be enough.”</em></p>

<p>Pretty depressing things to start saying to yourself at 12, but I didn’t know any better yet. I tried as hard as I could for so many years, with everything. Sure, I got accolades, great grades, good opportunities, and met some amazing people. But still, there was a cost, a sacrifice. If you only live to work, then you have to kind of give up on living. You have to give up on your humanity, at least a little bit. At least, with the way I was going about things, successes meant both everything and nothing, especially when I was always over-preparing for the next potential failure around the corner.</p>

<p>Especially now, looking back on college, I think about things I could’ve done, the people I would’ve let myself be happy around, if I didn’t start following that sort of hustle culture so early. I was so convinced that I had to work in order to live, that I couldn’t just ‘live’. My life was my job, my classes, my projects. I worked alone and had to mask in front of everyone. Just like in the games I so dearly loved, there were metrics, and if I wasn’t treating life like a game to master, then I wasn’t playing correctly.</p>

<p>There’s another quote that I love by NFL coach Bill Walsh, which reads</p>
<blockquote>
  <p>“The score takes care of itself.”</p>
</blockquote>

<p>That’s true for both games and life. You forget to enjoy the game if you’re only focused on a high score. You forget to live life if you’re only focused on the metrics. The more you live your life chasing those high scores, the less of a ‘high’ you’ll probably get each time.</p>

<p>Now, at 23, it takes vastly more effort for me to relax than it does to not. It’s a vicious cycle, working as hard as I can for as long as I can, getting inevitably burnt out, resting without peace, then working as hard as I can again, then eventually looking back on what I could’ve done instead without sacrificing so much. Like Vader, you “become more machine now than man.”</p>

<h2 id="so-whats-next">So, what’s next?</h2>
<p>Why am I spending so much time talking about this? Because that ‘perfect’ schedule I made was nice for a while, but the pain of seeing it slip away triggered a lot. It was a really painful but necessary reminder that we need to grow up, that perfection isn’t the way to live, that a schedule and life deserve to be more than just a checklist of never-ending items.</p>

<p>Fortunately, I’ve been grateful enough to get to connect with lots of wise family, friends, entrepreneurs, and self-starters. They’ve given great advice and, along with some excellent <a href="https://www.youtube.com/watch?v=EISvtpA1Eys">YouTube videos</a>, I’ve taken away so far the following lessons:</p>

<ul>
  <li><em>just write down 2-3 things you need to do each day</em></li>
  <li><em>move from a ‘i have to’ mindset to a ‘i get to’ mindset</em></li>
  <li><em>do processes, not goals</em></li>
  <li><em>check in with yourself each week, be honest</em></li>
  <li><em>take time for spiritual practice and community</em></li>
  <li><em>work off your own energy, recognize when your mind is most &amp; least active</em></li>
  <li><em>have specific routines for your morning and night</em></li>
</ul>

<h2 id="the-first-draft">The First Draft</h2>
<p>As the first step towards really maturing my schedule, here’s the first draft of that new life:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-24-02/schedule2.jpg" style="max-width:600px;" />
</p>

<p>As you can see, we’ve got more ‘guidelines’ than anything. Hardly any time-blocks, just general rules to try and follow. Some are per-day, some are per-week. No more “work out at exactly 6:30 am every morning”, now it’s just “aim for at least 3 sessions per week.” What I love about this is that it gives me flexibility, so that if there’s hypothetically a kickboxing class at 6:30 pm, then I’ll be able to join without burning myself out! No more crazy strict routines, now it’s just “work on your checklist between 9-5, enjoy life.” It’s even got my new favorite mantra at the bottom,</p>

<p><strong><em>We get to</em></strong></p>

<p>Hell, I might even get that tattooed one day. I’ll still probably use my Google Calendar, but likely only for scheduled meetings and events, and nutrition timing. This new ‘schedule’ is bare-bones, unoptimized, and… human. It’ll take some getting used to, but it’s more than worth the risk. I’m also going to be checking in with myself every week to see how I actually feel, instead of just pushing forward.</p>

<p>To the future, to life uncaged by metrics, to games played without score, to the curious and nonsensical ways of our world!</p>

<blockquote>
  <p>“One of my wise teachers, Dr. William F. Orr, told me, ‘There is only one thing evil cannot stand, and that is forgiveness.’ “ 
<cite><a href="https://www.goodreads.com/quotes/10222318-one-of-my-wise-teachers-dr-william-f-orr-told">Fred Rogers</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="burnout" /><category term="lifestyle" /><category term="games" /><summary type="html"><![CDATA[My recent experiences with burnout, and the pursuit of the perfect day]]></summary></entry><entry><title type="html">The Evolution of FrogRunner’s Gameplay</title><link href="https://gingerdeity.github.io/blog/frogrope/" rel="alternate" type="text/html" title="The Evolution of FrogRunner’s Gameplay" /><published>2026-02-17T00:00:00-05:00</published><updated>2026-02-17T00:00:00-05:00</updated><id>https://gingerdeity.github.io/blog/frogrope</id><content type="html" xml:base="https://gingerdeity.github.io/blog/frogrope/"><![CDATA[<h2 id="the-story-thus-far">The Story thus far</h2>
<p>For those who haven’t seen the <a href="https://gingerdeity.github.io/projects/frogrunner/">project page for Frogrunner</a>, FrogRunner is the codename of me and my team’s personal project game made in <em>Godot</em>. This is a platforming game, where you run and jump through levels, playing as a frog in a sci-fi mech suit! What makes this different from other platforming games is that the main mechanic revolves around you using your frog’s tongue to grapple and swing around, building momentum that allows you to launch yourself through space!</p>

<p>However, our first foray into 3D games required a lot of research, and getting our pendulum-based physics took far longer than we would have expected. Our first commit for this project dates back to Sep. 26th, 2025, and since then, we’ve evolved the mechanics of our grappling game numerous times.</p>

<p>One misconception I find a lot of people outside of the programming/game-development world tend to have is that these fields don’t share that ‘iterative’ trait you find in creative works. When working on a painting, or writing a novel, or editing a movie, you must iterate over the piece until it’s as close to what you wanted as possible. But some people seem to think that doesn’t apply to fields as involved in logic and math as game development or programming is.</p>

<p>I wanted to make a post that could show otherwise, and show my personal journey with how I’ve gone about programming this! Each ‘snapshot’ will show a video of the movement, as well as comments on how it feels and improvements, and some will even have pseudocode showing the logic. Without further ado, let’s get started with the snapshots.</p>

<h2 id="current-build">Current Build</h2>
<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/videos/frogrunner_preview.mp4" type="video/mp4" />
</video>

<p><strong><em>Commit date: Jan. 28th, 2026</em></strong></p>

<p>As a refresher, this is the current state of our game, and honestly, I’m very happy. The controls feel tight, the movement is fluid, and building up momentum feels very natural. There are even ‘hidden’ techniques like being able to jump out of your swing and launching yourself more vertically. Overall, the different platforming systems of swinging, launching, running, jumping, and reeling in/out all work together really well. Feel free to try it out by downloading <a href="/assets/downloads/FrogRunner.zip">here</a>.</p>

<p>Now, let’s go back to one of our very first project commits.</p>

<h2 id="spring-movement">Spring Movement</h2>
<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-17-02/fr_rope1.mp4" type="video/mp4" />
</video>

<p><strong><em>Commit date: Sep. 29th, 2025</em></strong></p>

<p>This is one of the earliest project commits I could find with a rope/tongue implemented. As you can see, there is <strong>no pendulum movement</strong>, and the rope acts more like a simple spring.</p>

<p>There’s also no limit to how far horizontally you can move yourself around. It’s an overall very awkward and unintuitive experience, but it was sufficient enough as an exercise in figuring out how we could apply vectors to our velocity and position!</p>

<p>The spring mechanics were implemented using <a href="https://www.youtube.com/watch?v=yWRHMOqoxGM">this tutorial</a>, and the main logic for the spring is shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func handle_grapple(delta: float):
  displacement = distance_to_target - spring_rest_length   # how much spring is being stretched
  
  force = Vector3.ZERO
  if displacement &gt; 0:
    spring_force_magnitude = spring_stiffness * displacement
    spring_force = direction_to_target * spring_force_magnitude
    velocity_dot_product = player.velocity.dot(direction_to_target)
    force = spring_force + (-damping * velocity_dot * target_dir)
  
  player.velocity += force * delta
</code></pre></div></div>

<h2 id="hookshot-movement-and-auto-reeling">Hookshot Movement and Auto-Reeling</h2>
<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-17-02/fr_rope2.mp4" type="video/mp4" />
</video>

<p><strong><em>Commit date: Oct. 18th, 2025</em></strong></p>

<p>As you can see, by Month 2, we had moved on from the spring-based movement and used our new understanding of vectors in the Godot game engine to make our player move more like Link when using his Hookshot tool in The Legend of Zelda franchise!</p>

<p>What I mean is, the rope would automatically start reeling you towards your destination the moment you shoot it. While the feel was still very awkward, it was a definite improvement over our spring movement and felt much closer to our original vision.</p>

<p>The main code for this became a lot simpler, shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func handle_grapple(target : Vector3) -&gt; void: 
  velocity = global_position.direction_to(target) * grapple_speed
</code></pre></div></div>

<h2 id="early-pendulum-movement--manual-reeling">Early Pendulum Movement &amp; Manual Reeling</h2>
<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-17-02/fr_rope3.mp4" type="video/mp4" />
</video>

<p><strong><em>Commit date: Oct. 20th, 2025</em></strong></p>

<p>Surprisingly enough, upon digging through the old commits for this project, we started adding in the pendulum movements only <em>two days later!</em> I remember having to teach myself a lot of pendulum physics, and brush up on general vector-math and trigonometry, so seeing that I was able to act on those refreshers so quickly was surprising!</p>

<p>Now, to be completely honest, the initial implementation of pendulum physics was done with ChatGPT, but I made sure to take the time to fully understand and comment every line it gave me. I was even able to later improve on the original responses I got from the AI, both in terms of performance and readability, and am much more confident in my game-dev skills as a result.</p>

<p>Here’s some of the most important code for pendulum movement:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func reel_move(target: Vector3) -&gt; void: 
  velocity = player.position.direction_to(target) * (speed + grapple_speed)

func pendulum_move(delta: float) -&gt; void:
  n = (bob_position - pivot_point).normalized() # 3d vector, direction from pivot to bob
  g = Vector3(0, gravity, 0) # 3d gravity vector

  a_tan = g - n * g.dot(n) # tangential acceleration, removes parallel forces that move us closer/further to the rope

  bob_velocity += a_tan * delta # calculate velocity
  bob_velocity *= damping # apply damping
  bob_velocity -= n * bob_velocity.dot(n) # again remove any forces that move us closer/further to the rope

  # apply corrected bob_velocity to character's velocity
  bob_position += bob_velocity * delta
  n = (bob_position - pivot_point).normalized()
  bob_position = pivot_point + n * rope_arm_length
  velocity = (bob_position - player.position) / delta
</code></pre></div></div>

<p>As you can see, there are still two distinct physics being applied based on whether you’re reeling towards the target or not. Yes, by this point, reeling towards your target was done manually by left-clicking.</p>

<p>By this point, the game was feeling much better, but the fact that our reeling in was instantly negating the pendulum physics felt off, and there were clearly still bugs. You can see at the end of the video that the rope was changing size based on how fast we were moving, not ideal.</p>

<h2 id="evolved-pendulum-movement">Evolved Pendulum Movement</h2>
<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-17-02/fr_rope4.mp4" type="video/mp4" />
</video>

<p><strong><em>Commit date: Nov. 19th, 2025</em></strong></p>

<p>About a month later, we had finally merged the reeling and pendulum physics and had fixed bugs correlated to rope size. The movement was finally feeling <em>buttery smooth, fluid, dynamic</em>. Everything was flowing and working together! We adapted our reeling as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func reel_move(target: Vector3, reeling_in_or_out: bool) -&gt; void: 
  direction = reeling_in_or_out * player.position.direction_to(target)
  velocity = lerp(velocity, direction * speed, reeling_acc)
  arm_length = get_distance_to_target()
</code></pre></div></div>

<p>You can see in the video an early ‘echo-trail’ effect. There were also still some bugs with reeling in and out while in pendulum-motion. Still, however, the movement had drastically improved, and the whole game felt much better.</p>

<h2 id="current-movement-and-future-plans">Current Movement and Future Plans</h2>
<video autoplay="" muted="" loop="" playsinline="" controls="" width="100%">
  <source src="/assets/posts/2026-17-02/fr_rope_current.mp4" type="video/mp4" />
</video>

<p><strong><em>Commit Date: Jan. 28th, 2026</em></strong></p>

<p>Now, all the earlier bugs have been fixed, the controls are even comfier, and we’ve added mechanics like jumping out of your pendulum mid-swing, and more! While I’m very happy with current progress, there’s still a lot to work on, and many questions and game-design paradigms to answer, such as:</p>

<ul>
  <li>Handling rope collisions
    <ul>
      <li>What do we do when we’re swinging, and an object comes into collision with our rope? Should we destroy/retract the rope?</li>
      <li>If we’re too strict, then the movement could suffer greatly, and being able to do full circles around objects could be impossible</li>
      <li>If we’re not strict enough, then game-breaking glitches could occur, and you’ll be able to grapple through walls</li>
    </ul>
  </li>
  <li>‘Stilts movement’
    <ul>
      <li>Because of how we’ve coded the physics, the rope has a fixed-length that is only changed when reeling in or out. However, if we launch our rope out at an odd angle (especially when we’re right above our target), that fixed-length suddenly turns our rope into a stilt, and movement halts! You can see this in the video a few times.</li>
    </ul>
  </li>
  <li>‘Hard’ rope vs ‘soft’ rope
    <ul>
      <li>Should we switch from a rope with a fixed length to a more ‘fluid’ and flexible rope? What’s the right approach?</li>
    </ul>
  </li>
</ul>

<p>Our current plan is to actually go back and borrow concepts from our <em>very first rope</em>! We think adding in some of the original springiness could fix lots of the above issues, acting both as a solution to the stilt-like movement and as a good balance between a hard and soft rope.</p>

<h2 id="final-thoughts">Final Thoughts</h2>
<p>Our first commit for this project dates back to Sep. 26th, 2025, and we’ve been working on this on-and-off ever since then. This is by far the most time I’ve ever spent on a personal project, and for our first time trying to make a 3D game, I’m very satisfied so far!</p>

<p>Every other project, whether for school or work, has always had strict deadlines or requirements. There was never as much time to make the game or code that I wanted, or I lacked the experience. After graduating from college, I felt a lot of doubt and insecurity about my ability to code or direct a project. It was terrifying, I was basically facing the reality that maybe the last few years of school, the months of sacrificing sleep and mental-wellbeing, and the several thousand dollars worth of my own hard-earned money, were all spent on a major I wasn’t good at, or maybe didn’t want to be good at anymore.</p>

<p>This project was the exact eye-opener I needed after graduating. I found myself voluntarily staying up late working on it, researching game mechanics and physics, even relearning Blender! I wasn’t just building a game; I found myself building systems and procedures for creating levels, modifying physics, changing and viewing debugging variables, and more! The fact that I’ve been able to do it with friends has undoubtedly been the best part.</p>

<p>I’m very proud of what’s been accomplished so far, and I still hold true to eventually releasing this as a demo on Steam at some point! Until the next Antholog…</p>

<blockquote>
  <p>“Work hard, study well, and eat and sleep plenty! That’s the Turtle Hermit way to learn!”<br />
<cite><a href="https://www.youtube.com/watch?v=fXMrZvcduOw">Master Roshi</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="godot" /><category term="game dev" /><category term="physics" /><summary type="html"><![CDATA[The current journey of our personal game's grappling mechanics, from springs to swings and beyond!]]></summary></entry><entry><title type="html">Tetris NES, Deep Dive #1</title><link href="https://gingerdeity.github.io/blog/tetrisnes1/" rel="alternate" type="text/html" title="Tetris NES, Deep Dive #1" /><published>2026-02-10T00:00:00-05:00</published><updated>2026-02-10T00:00:00-05:00</updated><id>https://gingerdeity.github.io/blog/tetrisnes1</id><content type="html" xml:base="https://gingerdeity.github.io/blog/tetrisnes1/"><![CDATA[<h2 id="the-story-so-far">The Story so Far…</h2>
<p>This was a school project during my last semester of college, for a reverse-engineering class. Me and another student worked together to try and add new mechanics to Tetris, the version released for the NES. Honestly, my original report does a pretty good job explaining it:</p>

<blockquote>
  <p>“Tetris is one of those classic games everyone knows about, and the version built for the Nintendo Entertainment System (NES) is one of the most famous renditions of that classic! However, this game was created in 1989, just two years before the Standard Rotation System (a system nearly all subsequent Tetris games followed) was created. As a result of this, the NES version used its own system that is significantly different from its successors. In this project, we intended to add in as many aspects of the Standard Rotation System (SRS) as much as possible. This revolved around two major features: adding in missing piece rotations, and adding in wall-kicking!”
<cite><a>Me, trying very hard to ‘write good’</a></cite></p>
</blockquote>

<p>That’s right, this version of Tetris is actually <em>missing</em> pieces so to speak, and can seen quite plainly when you look at all possible rotations in the game:</p>
<p style="text-align:center;">
  <img src="/assets/images/TetrisNES/tetris_nes.png" style="max-width:600px;" />
</p>

<p>It becomes quite clear that we’re missing rotations for the I, S, and Z blocks (top to bottom). In reality, these blocks should have 4 rotations like so:</p>
<p style="text-align:center;">
  <img src="/assets/images/TetrisNES/tetris_nes_ideal.png" style="max-width:600px;" />
</p>

<p>This is actually also taken directly from our final report, and shows my final plan for adding these pieces to the game. However, due to certain problems with NES hardware (that I fully intend to explore in a future post), this was not entirely feasible. I was able to get all the new rotations, but had to remove the I-block from the game.</p>

<p>All in all, I look back on this project with a lot of pride, but also shame that I never got to reach my full vision.</p>

<h2 id="why-bring-up-the-story-now">Why bring up the story now?</h2>
<p>As much as I would love to only focus on the <em>new</em> and <em>exciting</em> systems and projects that I’m working on that aren’t <em>implemented like a monkey to a typewriter</em>, I feel that would do a disservice to this Antholog. Looking back at what went wrong is important, and it makes us human.</p>

<p>I actually do plan to <strong>finish this project</strong>, for the time being at least! The worst part about this project was that I had very little time to dedicate to it. My last semester I was dealing with:</p>
<ul>
  <li>4 other intense classes</li>
  <li>2 group projects, including this one</li>
  <li>helping run a club</li>
  <li>working 20 hours a week doing my <a href="https://gingerdeity.github.io/projects/deduplication/">research</a></li>
  <li>coordinating my graduation plans</li>
</ul>

<p>I also had… absolutely no idea what I was doing. It was my first time trying to reverse-engineer an NES game, and it turns out assembly was a <strong>lot</strong> tougher than I remembered! There was a lot to learn, and no time to understand it all. So, I want to study this project, and explore what I could’ve done better, and either update the old GitHub or create a new one!</p>

<h2 id="what-is-the-final-project">What is the Final Project?</h2>
<p>In our original school project, my teammate focused on adding wallkicks, while I was given the task of adding the new rotations. Quite simply, I want to be able to finish what I started by adding in the missing rotations while not sacrificing any blocks from the game. I’ve also recently been inspired by <a href="https://www.reddit.com/r/Tetris/comments/1dceffg/nes_tetris_with_hard_drop_ghost_piece_7digit/">other hacks</a> I’ve seen for this game, so I may end up adding other mechanics too!</p>

<p>For the time being however a final hack will:</p>
<ul>
  <li>add in the missing rotations for the I, S, and Z blocks</li>
  <li>be able to update the score and statistics in the game properly</li>
</ul>

<p>There were also several difficulties with the development environment we used, which I plan on also fixing.</p>

<h2 id="one-last-problem">One last problem</h2>
<p>This post is going to go into very technical details of just <em>one</em> aspect of this project that I’ve tried to fix since last week. But before we delve into that, it’s important to note one <strong>major</strong> technical challenge for this project, because I’m sure some people may already have a good suggestion for how we should’ve started this project. Normally, it’s great advice to just using an already <a href="https://github.com/CelestialAmber/TetrisNESDisasm">decompiled version</a> of the game to expedite translating the code. However, we had to…</p>

<p><strong>Build Our Own Decompilation</strong><br />
We just didn’t think we could feasibly or ethically get away with using an already decompiled version of this game. Again, this was a <em>reverse-engineering class</em>, the whole curriculum was about using tools like Ghidra and hex editors to be able to dissect and translate disassembled files.</p>

<p>Me and my teammate both agreed it would’ve been moot and not in the spirit of the class to use a decompilation that essentially did all of this for us. However, this would be a significant issue because you tend to lose a <em>lot</em> of information when disassembling any executable from scratch. Most, if not all, variable and function names are gone, and for these ancient NES games those names served as HUGE hints for understanding functionality. Oh, and comments? No, no comments remain here. This is barren land, and it made the project exponentially harder.</p>

<h2 id="so-where-do-we-start">So, where do we start?</h2>
<p>If we’re gonna do this project justice, we need to start with the basics, that being the development environment and configuration file itself. Our development environment is simple enough, containing all the tools we’d need, like an assembler, disassembler, procedures for both, and a way to play the game. Fortunately, with the help of a masterful <a href="https://www.youtube.com/watch?v=RtY5FV5TrIU&amp;t=17s">tutorial</a>, this part was relatively easy. Again, this environment can be found on the <a href="https://github.com/GingerDeity/TetrisNES">GitHub</a>.</p>

<p>However, my first issue came when I realized that we would need to describe a custom config file for the assembler to properly create an playable file. I don’t remember how I learned to program this but, after researching NES development and doing lots of chats with Claude, I’ve found some massive problems with the original:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SYMBOLS {
    __STACKSIZE__: type = weak, value = $0300;
}
MEMORY {
    ZP:     file = "", start = $0002, size = $001A, type = rw, define = yes;
    HEADER: file = %O, start = $0000, size = $0010, fill = yes;
    ROM0:   file = %O, start = $8000, size = $7FFA, fill = yes, define = yes;
    ROMV:   file = %O, start = $FFFA, size = $0006, fill = yes;
    ROM2:   file = %O, start = $0000, size = $4000, fill = yes;
    SRAM:   file = "", start = $0500, size = __STACKSIZE__, define = yes;
    RAM:    file = "", start = $6000, size = $2000, define = yes;
}
SEGMENTS {
    ZEROPAGE: load = ZP,              type = zp;
    HEADER:   load = HEADER,          type = ro;
    LOWCODE:  load = ROM0,            type = ro,  optional = yes;
    ONCE:     load = ROM0,            type = ro,  optional = yes;
    CODE:     load = ROM0,            type = ro,  define   = yes;
    RODATA:   load = ROM0,            type = ro,  define   = yes;
    DATA:     load = ROM0, run = RAM, type = rw,  define   = yes;
    VECTORS:  load = ROMV,            type = rw;
    BSS:      load = RAM,             type = bss, define   = yes;
    CHR:    load = ROM2,            type = rw;
}
FEATURES {
    CONDES: type    = constructor,
            label   = __CONSTRUCTOR_TABLE__,
            count   = __CONSTRUCTOR_COUNT__,
            segment = ONCE;
    CONDES: type    = destructor,
            label   = __DESTRUCTOR_TABLE__,
            count   = __DESTRUCTOR_COUNT__,
            segment = RODATA;
    CONDES: type    = interruptor,
            label   = __INTERRUPTOR_TABLE__,
            count   = __INTERRUPTOR_COUNT__,
            segment = RODATA,
            import  = __CALLIRQ__;
}
</code></pre></div></div>

<p>In the end, I was able to switch my config file out for the one in the completed decompilation, but in the process was able to learn everything that I <em>should have</em> when it comes to these config files. Here’s the current config file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MEMORY {
    HDR: start = $0000, size = $0010, fill = yes, fillval = $00;
    PRG: start = $8000, size = $8000, fill = yes, fillval = $00;
    CHR: start = $0000, size = $4000, fill = yes, fillval = $00;

    ZP:  start = $0000, size = $0100, type = rw, file = "";
    RAM: start = $0100, size = $1F00, type = rw, file = "";
}
SEGMENTS {
    ZEROPAGE: load = ZP,                 type = zp;
    BSS:      load = RAM,                type = bss;
    HEADER:   load = HDR,                type = ro;
    CHR:      load = CHR,                type = rw;
    CODE:     load = PRG,                type = ro;
    VECTORS:  load = PRG, start = $FFFA, type = ro;
}
</code></pre></div></div>

<p>That’s it! It’s much more readable and does the exact same thing as the old one. The two biggest issues came from:</p>

<p>1) Cross-referencing with the completed disassembly I linked to earlier, and looking at the ld65 documentation, the <code class="language-plaintext highlighter-rouge">FEATURES</code> and <code class="language-plaintext highlighter-rouge">SYMBOLS</code> sections seem to be entirely optional. We can remove these without issue</p>

<p>2) I had no idea what the <code class="language-plaintext highlighter-rouge">MEMORY</code> or <code class="language-plaintext highlighter-rouge">SEGMENTS</code> sections did, but after much research and chatting with other developers and Claude AI, I’ve come to understand it much better</p>

<h2 id="what-ive-learned-so-far">What I’ve learned so far</h2>
<p>NES ROMs all use the iNES file format, and in that format we’re mostly concerned with the following sections:</p>

<p>1) Header (describes overall file layout, 16B)</p>

<p>2) PRG ROM data (code and data banks, 16KB per bank)</p>

<p>3) CHR ROM data, if present (graphics banks, 8KB per bank)</p>

<p><strong>MEMORY Section</strong></p>

<p>In the NES, the PRG ROM is interpreted by the CPU, whereas the CHR ROM is interpreted by the PPU (Picture-Processing Unit). In the CPU, the PRG ROM is given addresses <code class="language-plaintext highlighter-rouge">$8000-$FFFF</code>, and the graphics start immediately in the PPU. This is what the <code class="language-plaintext highlighter-rouge">MEMORY</code> section in our config is for, it essentially gives the correct labels to our PRG and CHR banks in our file to our header, so that emulators can do the correct address math. You’ll notice the line:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PRG: start = $8000, size = $8000, fill = yes, fillval = $00;
</code></pre></div></div>

<p>follows the exact standards of the NES’s CPU, starting at the correct address and filling 2 banks (32KB total). It’s also why we give the CHR ROM <code class="language-plaintext highlighter-rouge">start = $0000</code>, even though iNES dictates that CHR ROM goes after PRG ROM. It’s because this <code class="language-plaintext highlighter-rouge">start</code> is for the PPU, not the CPU!</p>

<p>Also, As I found through painful experimentation, it’s also <strong>very</strong> important you have the header, program data, and character data listed in <strong><em>that exact order</em></strong>, as otherwise the header will tell basically emulators that the program data is located where the character data is, and vice-versa, making the game unplayable.</p>

<p><strong>SEGMENT Section</strong></p>

<p>As for the <code class="language-plaintext highlighter-rouge">SEGMENTS</code> section, this simply goes through our code, looking for the segments in it’s list, and loading those segments to the correct areas of memory. So, our <code class="language-plaintext highlighter-rouge">CODE</code> segment will correctly load into the PRG-ROM section, and so on.</p>

<p>One important distinction is the <code class="language-plaintext highlighter-rouge">VECTORS</code> segment, which holds the data for initializing the game when the console powers-on, and more. If the game doesn’t have the correct location for these pointers, then the game won’t be able to start correctly. This is going to be located in our PRG ROM, but we need the emulator to know exactly <em>where</em>, hence the <code class="language-plaintext highlighter-rouge">start</code> variable. Doing some math we can see that, in our final NES file, the location of the vectors will be:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     $FFFA (location in emulated CPU's memory)
    -$8000 (location of PRG-ROM in emulated CPU's memory)
    ------
    =$7FFA (file offset into PRG-ROM)
    +$0010 (addition file offset from header)
    ------
    =$800A (file location of VECTORS)
</code></pre></div></div>

<p>Looking at $800A in the hex editor for our compiled NES file, you’ll find 6 bytes, 2 for each pointer for the three vectors your game needs to start!</p>

<p><strong>Summary</strong></p>

<ul>
  <li>The config file is responsible for detailing the correct specifications to be stored in the final ROM so that corresponding emulators can play the game correctly</li>
  <li>The <code class="language-plaintext highlighter-rouge">SEGMENTS</code> section starts by correctly assigning the segments to the <code class="language-plaintext highlighter-rouge">MEMORY</code> areas the emulator will look through. <code class="language-plaintext highlighter-rouge">CODE</code> goes to PRG and <code class="language-plaintext highlighter-rouge">CHR</code> goes to CHR.</li>
  <li>The <code class="language-plaintext highlighter-rouge">VECTORS</code> segment is given further information so you can still find it even when hidden in the program data</li>
  <li>The <code class="language-plaintext highlighter-rouge">MEMORY</code> section gives the correct <code class="language-plaintext highlighter-rouge">start</code> and <code class="language-plaintext highlighter-rouge">size</code> specifications to adhere to NES address math</li>
  <li>The combination of the two results in a playable file</li>
</ul>

<h2 id="whats-next">What’s next?</h2>
<p>In the old project, another significant challenge was that, for some reason, when adding or removing code in the middle of the PRG-ROM data, the game would show a blank green screen upon startup. Observe! The green screen of death and my current debugging attempt:</p>
<p style="text-align:center;">
  <img src="/assets/posts/2026-10-02/green_screen_of_death.png" style="max-width:600px;" />
</p>

<p>This made development even <strong><em>more impossible</em></strong>, as we had to be insanely careful with how we were writing code. We had to add our functions to the end of the established code, add padding bytes where needed, and be very careful if we ever did write code in the middle of the PRG-ROM segment.</p>

<p>Upon revisiting this project, I had a new theory, that if I fixed the config file to more forcefully insert our <code class="language-plaintext highlighter-rouge">VECTORS</code> data, that we would make it past start-up. After all, these are the pieces of data that deal the most with when the game first boots-up. Surely, if I fixed this config then I would be able to add and remove code as needed!</p>

<p>Unfortunately, that’s not the case. When trying to remove certain functions that go completely unused in the game, this green screen of death happens more than you’d ever want. I’ve tried changing the config file, the assembler and disassembler settings, and more, but still nothing. At this point, there are two paths in front of me:</p>

<p>1) Continue debugging and making my own disassembly work</p>

<p>2) Start working and hacking on an already finished disassembly</p>

<p>I’ve yet to decide, but will make up my mind in the following weeks.</p>

<h2 id="final-thoughts">Final Thoughts</h2>
<p>This is a very hard project, but also greatly touches upon what I love about these retro games. I feel that it’s often very easy to take what society offers for granted. There have been so many times in my life where I’m walking through the city and stop for a brief moment, gazing at a building, only to say to myself,</p>

<p><em>“Wow, look at all those bricks, all just on this one wall. There are dozens here, that had to be made, transported, and glued in place here. Then you have to do that for all the other walls, and that’s not even considering the foundation, or roof, or floors, or anything else. This single wall of bricks is amazing, I don’t think I’ll ever take walls like this for granted ever again.”</em></p>

<p>But we do. We do forget just how extraordinary the ordinary is, and who can blame us? Life is hard enough, and if we spent all day only focusing on what came before, we wouldn’t get anywhere. In the world of computers, it’s incredibly easy to take things like memory or computing speed for granted. Gigabytes are in places where megabytes used to be a dream, and processors are always faster than before. Even the languages we code in are readable and at least somewhat akin to the tenets of English!</p>

<p>Then you go back just 40 years ago. You look at the intense rigidity and limitations developers had to work with. You see how important every single byte was, you see the ingenious tricks and techniques they had to do just to make stuff show up on a screen. The ROM file for Super Mario Bros. is 40KB, that’s about as much as a single <em>screenshot</em> of a game!</p>

<p>These games are… black magic. By all limits and reason, they shouldn’t exist. Why go to so much trouble? Why do so much for so little?</p>

<p>Because to create anything meaningful and to do it well is to embrace the restraints. To do as much as you can with the limited tools at your disposal, to force yourself to be <em>that</em> good. <em>Then</em>, and only then, should your artistic shackles become removed. Just like when I was a kid, you don’t get to use the calculator if you don’t know how to multiply by yourself.</p>

<p>I love magic, and these older games are it. They take nothing, and make <em>everything</em> out of it.</p>

<blockquote>
  <p>“I think that inside every adult is the heart of a child. We just gradually convince ourselves that we have to act more like adults.” 
<cite><a href="https://www.azquotes.com/author/10225-Shigeru_Miyamoto">Shigeru Miyamoto</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="romhack" /><category term="game dev" /><category term="assembly" /><summary type="html"><![CDATA[The first post, telling the story of how I attempted to add *missing pieces* back into this iconic game, and the journey ahead...]]></summary></entry><entry><title type="html">Hello, World!</title><link href="https://gingerdeity.github.io/blog/welcome/" rel="alternate" type="text/html" title="Hello, World!" /><published>2026-02-03T00:00:00-05:00</published><updated>2026-02-03T00:00:00-05:00</updated><id>https://gingerdeity.github.io/blog/welcome</id><content type="html" xml:base="https://gingerdeity.github.io/blog/welcome/"><![CDATA[<p>Welcome to the very first of my blog posts!</p>

<!--more-->

<p>Man, there’s so much I could talk about, so much I want to talk about, but I guess I should start with the basics, like:</p>

<h2 id="why-did-i-make-this-site">Why did I make this site?</h2>
<p>Above all, I just really wanted my own way to help tell people who I really am! I wanted to show what I’ve already accomplished, what I’m currently doing, and what I plan on in the future. Hence, I divided the site into two main parts, the first being this very blog, and the second part being a <a href="https://gingerdeity.github.io/projects/">compilation of projects</a>.</p>

<p>The other reason for making this site? I really wanted a way to incentivize my continued learning! This blog, while personal and will share many personal thoughts and feelings, will also act as a weekly progress report on projects. I’m someone very new to this career space, and I want employers and coworkers to look at this and in one glance realize ‘oh, this is someone who is disciplined and always learning!’</p>

<p>That’s yet another huge motivation for me, this is intended as a way to help me learn <em>discipline over passion</em>, to remember how to run on fuel, not flames. It’s here to show my journey as I continually become both a better <em>student and teacher</em> for myself and others. It’s here to remind me to always enjoy this <em>neverending process</em>, and to encourage sharing that.</p>

<h2 id="what-should-you-expect">What should you expect?</h2>
<p>If you happened to click on my <a href="https://www.linkedin.com/in/atreyu-mclewin-a48b5528a/">LinkedIn profile</a> (thank you if you did!), hopefully you’ll have noticed the banner:</p>

<p style="text-align:center;">
  <img src="/assets/posts/2026-03-02/LinkedInBanner.png" style="max-width:600px;" />
</p>

<p><strong>Programmer by Trade</strong><br />
My specialty and main interest is programming. You’ll see a lot of posts and projects that either are programming-oriented or, at the very least, programming-adjacent. Expect many projects or progress reports revolving around languages like Python, C++, JS, etc!</p>

<p><strong>Designer by Mindset</strong><br />
Even though programming is my career, don’t be surprised to see posts or thoughts that have more to do with design and the design process! My parents were theatre, art, and philosophy majors, and a good portion of that definitely transferred into me (love you mom and dad :D).</p>

<p><strong>Game Developer at Heart</strong><br />
Games have been a huge part of my life ever since I was a child. I find the form of storytelling in games to be the most incredibly fascinating form of storytelling so far. In nearly all other avenues of storytelling, the audience is rarely anything more than passive spectators. But in games? You become the active participant. Games like <em>Ocarina of Time</em> didn’t just tell or show me heroics, it allowed me to <em>practice</em> heroics, games like <em>Star Wars Battlefront II</em> let me practice strategy, <em>Portal 2</em> got me interested in science, the list goes on.</p>

<p>I am a programmer by trade, with a designer mindset, who loves making and playing games. Expect a lot of projects and posts about that.</p>

<h2 id="whats-next">What’s next?</h2>
<p>There are <em>several</em> projects I could go back and touch up, but right now, here’s the current plan:</p>
<ul>
  <li>Start learning JS and HTML</li>
  <li>Continue development of Frog Runner</li>
</ul>

<p>I have very little experience with JS, and I just love how far the Frog Runner prototype has come so far! My brother just recently finished the character concept pieces, so we’ll hopefully be adding in 3D models of those drawings soon enough.</p>

<h2 id="final-thoughts">Final Thoughts</h2>
<p>I’m really excited to finally have a place where I’m confident to show off my projects, and a place that’ll motivate me to keep learning this profession! I can’t wait to share more with you all. That’s all for now folks, until next time!</p>

<blockquote>
  <p>“Human passions have mysterious ways, in children as well as grown-ups. Those affected by them can’t explain them, and those who haven’t known them have no understanding of them at all.” 
<cite><a href="https://www.goodreads.com/work/quotes/1122661-die-unendliche-geschichte">Michael Ende</a></cite></p>
</blockquote>]]></content><author><name>Atreyu McLewin</name></author><category term="blog" /><category term="update" /><summary type="html"><![CDATA[Welcome to the very first of my blog posts!]]></summary></entry></feed>