<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="https://www.vxyz.me/rss.xml" rel="self" type="application/rss+xml" />
<title>vxyz.me</title>
<link>https://www.vxyz.me</link>
<description>Variant's blog</description>
<item>
<title>Hello World!</title>
<description><![CDATA[<p>Copied over my Cohost intro post below since it covers me for the most part <small>(not me waiting until the very last minute to copy things over from Cohost)</small>, but my hope with this blog was to serve as a place to help get me to write thoughts down so I can reference them later starting in this upcoming 2025.</p>

<p>The added bonus of figuring out what goes into frontend web development is nice too. </p>

<hr />

<p><details>
<summary><em>Cohost Intro Post</em></summary></p>

<p>I'm known in a few places as Variant, and my hope is that this'll serve as a useful intro pinned post.</p>

<p>I enjoy games, but don't actually have time to play too many of them. I tend to pick up and drop games if they don't grab me, so a lot of the ones I finish tend to be fairly special to me. Sometimes I'll come across a series or game that I really like and want to make better, or at least more palatable to myself, and so I tend to do a lot of reverse engineering projects...</p>

<p>In recent years, this has been a myriad of various Gameboy romhacking projects, like the <a href="https://github.com/Medabots">Medabots GB translations</a> (of which 1 and 3 are done, the rest are TBD), or throwing <a href="https://github.com/VariantXYZ/dragon-warrior-3-gbc">VWF into Dragon Warrior 3</a>.</p>

<p>I eventually want to translate a lesser known Link's Awakening-esque game called <a href="https://koei.fandom.com/wiki/Metamode">Metamode</a> as well, but that'll be a task for another day.</p>

<p>In past years, I worked on enabling translations for Phantasy Star Online 2 back when it came out, among other things. I was indirectly responsible for providing a way to track damage and healing metrics too.</p>

<p>A longer time ago, I actually was really into Ragnarok Online and the super high rate private server scene too. I had administrated more populated servers, but my favorite was definitely the last one I was involved in called RidiculouslyRO. A friend and I worked on it together and I think it was definitely something special. We went balls to the wall with Big Numbers and customization and even implemented solo instancing way before it was mainlined into the server emulator projects at the time...</p>

<p>And that's what I remember.</p>

<p></details></p>

<hr />

<p><sub>Realizing as I'm typing my first blog post that I forgot to support images... </sub></p>

<p><sub>More importantly, because everything is in a flat structure, it's definitely going to be a pain to properly isolate images per post... but maybe I can just call it a feature and have a common image directory.</sub></p>
]]></description>
<link>https://www.vxyz.me/00001.html</link>
<guid>https://www.vxyz.me/00001.html</guid>
<pubDate>Tue, 31 Dec 2024 14:23:02 -0800</pubDate>
</item>
<item>
<title>Variable Width Fonts and space efficiency</title>
<description><![CDATA[<p><sub>Disclaimer: I'm not even remotely proficient in Japanese, but I definitely deal with a lot of Japanese text in both my hobbies and at work, so I happen to have some observations on it.</sub></p>

<h1>Preface</h1>

<p>A <a href="https://www.science.org/doi/10.1126/sciadv.aaw2594">recent study</a> I saw popping up on some social media commented on how information density over time across spoken languages was fairly similar despite vastly different approaches (different syllable counts, general rate of speech, etc...). There are some obvious criticisms, of course. For example, language tends to bias towards specific cultural requirements and so there may be specific contexts where the language excels and conversely, specific ones where it falls short... but that aside, it did get me thinking a bit about <em>written</em> information density, especially when it comes to displaying things on fairly low-spec systems (<sub>yes I mean the Gameboy</sub>).</p>

<p>I've done a fair amount of reverse engineering on old GB stuff to enable translations from Japanese. I think I'm generally rather slow overall, but I do have a process:</p>

<ol>
<li>Identify what's writing the text out

<ul><li>Text is usually represented as a set of indices into a larger tileset</li></ul></li>
<li>Use the knowledge from (1) to figure out where the text itself is stored

<ul><li>Intuitively, text is probably being written out as part of a larger scripting system, but we generally don't need all of it to just translate text</li>
<li>Sometimes it's embedded in the script itself (like most old GBDK titles), which means we have to figure out the scripts to an extent anyway...</li></ul></li>
<li>(Optionally) Dump the tileset to png and allow fo rebuilding with it cleanly

<ul><li>Sometimes, like with Sakura Wars GB2, the text itself already supports English font so I just reuse it</li></ul></li>
<li>Extract the text into some common format (usually CSV) and rebuild with it cleanly (text extraction + reinsertion)</li>
</ol>

<p>Generally after text extraction/insertion, the next big task to overcome is... how do we actually fit English text in the space originally meant for Japanese text? ...The answer is usually "it depends" from game to game and I won't bore you with the details (<em>for now</em>).</p>

<p>Instead, with the above context, I'd rather dive in a bit into Japanese text itself and how exactly it compares to the translated English. Japanese text in old games tends to be fairly <a href="##" title="The number of pixels consumed on screen for text when it&#39;s displayed">space efficient</a> and <a href="##" title="The amount of data used to store the text in memory itself">storage efficient</a>. Since it's New Years' day and I'm tired from all the festivities, I'll just briefly talk space efficiency here.</p>

<h1>Space Efficiency in Dragon Warrior 3</h1>

<p>Randomly, on Cohost this year, a user <a href="http://x.com/Bek0ha">@Bek0ha</a> (<a href="https://bsky.app/profile/bekoha.bsky.social">bsky</a>) went and found and recreated a <a href="https://archive.org/details/jimaku-font">cool font</a> that caught my eye:</p>

<p><img src="kinema.png" alt="K.K. Kinema Font Lab" title="K.K. Kinema Font Lab - Handwritten Movie Subtitle Font" /></p>

<p>Bekoha went so far as to even provide me an 8x8 version of it:</p>

<p><style>
span.two img
{
    max-width: 49%;
    height: auto;
}
</style>
<span class="two"><img src="kinema_pixel.png" alt="Kinema 8-bit font" title="Standard Font" /> <img src="kinema_pixel_2.png" alt="Kinema 8-bit narrow font" title="Narrow Font" /></span></p>

<p>Anyway, I figured I'd see how it would look in Dragon Warrior 3, which I had <a href="https://github.com/VariantXYZ/dragon-warrior-3-gbc">disassembled</a> and gotten text reinsertion working for a while back for a re-localization project.</p>

<p><style>
span.gifs img
{
    max-width: 24%;
    height: auto;
}
</style></p>

<p><span class="gifs"><img src="dw3_normal_jp.gif" alt="Original Japanese" title="Original Japanese" /> <img src="dw3_normal.gif" alt="Original English" title="Original English" /> <img src="dw3_vwf.gif" alt="VWF English" title="VWF English" /> <img src="dw3_vwf_narrow.gif" alt="VWF Narrow English" title="VWF Narrow English" /></span></p>

<p><sub>From left to right: The original Japanese, the original English, Kinema 8-bit, and Kinema 8-bit narrow</sub></p>

<p>Let's look at these lines (note that things surrounded by brackets are a single tile):</p>

<p><details>
<summary>Line 1</summary></p>

<blockquote>
  <p>＊「[・・・][・・・]はあ　はあ.</p>
  
  <p>＊「ねえ!　オルテガさんの　子供が</p>
  
  <p>　　生まれたんですって!?</p>
  
  <p>[*:] Pant, pant…</p>
  
  <p>Is it true that</p>
  
  <p>Ortega had a baby?
  </details></p>
</blockquote>

<p><details><summary>Line 2</summary></p>

<blockquote>
  <p>＊「そうとも!　すごい元気な</p>
  
  <p>　　赤ちゃんだそうだ.</p>
  
  <p>[*:] That['s] right!</p>
  
  <p>I hear the baby['s]</p>
  
  <p>really lively too.
  </details></p>
</blockquote>

<p><details><summary>Line 3</summary></p>

<blockquote>
  <p>＊「アリアハンのゆうしゃ　オルテガの</p>
  
  <p>　　子どもなら[・・・]</p>
  
  <p>＊「きっと　りっぱな</p>
  
  <p>　　戦士になるぞ!</p>
  
  <p>[*:] Any child of</p>
  
  <p>Ortega, Aliahan['s]</p>
  
  <p>hero, is sure to</p>
  
  <p>become a great</p>
  
  <p>warrior.
  </details></p>
</blockquote>

<p><details><summary>Line 4</summary></p>

<blockquote>
  <p>＊「[・・・][・・・]そうよね.</p>
  
  <p>＊「さあ　早く　赤ちゃんのかおを</p>
  
  <p>　　見せてもらいましょう!</p>
  
  <p>[*:] That['s] true.</p>
  
  <p>We should go see</p>
  
  <p>the baby!
  </details></p>
</blockquote>

<p><sub>(Did you notice how the Japanese actually has enough leeway to indent lines around the asterisk? The English definitely didn't...)</sub></p>

<p>I suspect if you have some common variable-width font for English enabled, the English text actually looks like it takes significantly less space than the fixed-width Japanese:</p>

<p><code>
ねえ!　オルテガさんの　子供が 生まれたんですって!?
</code></p>

<p><code>
Is it true that Ortega had a baby?
</code></p>

<p>So let's see some stats as measured on the Gameboy:</p>

<p><style>
table.fonts
{
    width: 100%;
    border-collapse: collapse;
    margin: 0 auto;
}
th.fonts, td.fonts
{
    text-align: center;
    vertical-align: middle;
}
</style></p>

<table border="1" class="fonts">
    <tr>
        <th class="fonts">Line</th>
        <th class="fonts">JP Character Count</th>
        <th class="fonts">EN Character Count</th>
        <th class="fonts">JP Pixel Width</th>
        <th class="fonts">EN (Original) Pixel Width</th>
        <th class="fonts">EN (Kinema) Pixel Width</th>
        <th class="fonts">EN (Kinema Narrow) Pixel Width</th>
    </tr>
    <tr>
        <td class="fonts">1</td>
        <td class="fonts">10 + 17 + 13 = 40</td>
        <td class="fonts">13 + 15 + 18 = 46</td>
        <td class="fonts">80 + 136 + 104 = 320</td>
        <td class="fonts">104 + 120 + 144 = 368</td>
        <td class="fonts">74 + 132 + 68 = 274</td>
        <td class="fonts">56 + 124 + 24 = 204</td>
    </tr>
    <tr>
        <td class="fonts">2</td>
        <td class="fonts">14 + 11 = 25</td>
        <td class="fonts">14 + 16 + 18 = 48</td>
        <td class="fonts">112 + 88 = 200</td>
        <td class="fonts">112 + 128 + 144 = 384</td>
        <td class="fonts">88 + 140 + 58 = 286</td>
        <td class="fonts">66 + 136 + 16 = 218</td>
    </tr>
    <tr>
        <td class="fonts">3</td>
        <td class="fonts">18 + 8 + 10 + 9 = 45</td>
        <td class="fonts">14 + 16 + 16 + 14 + 8 = 68</td>
        <td class="fonts">144 + 64 + 80 + 72 = 360</td>
        <td class="fonts">112 + 128 + 128 + 112 + 64 = 544</td>
        <td class="fonts">126 + 130 + 108 + 48 = 412</td>
        <td class="fonts">140 + 140 + 36 = 316</td>
    </tr>
    <tr>
        <td class="fonts">4</td>
        <td class="fonts">9 + 16 + 13 = 38</td>
        <td class="fonts">13 + 16 + 9 = 38</td>
        <td class="fonts">72 + 128 + 104 = 304</td>
        <td class="fonts">104 + 128 + 72 = 304</td>
        <td class="fonts">80 + 122 + 34 = 236</td>
        <td class="fonts">60 + 120 = 180</td>
    </tr>
    <tr>
        <td class="fonts">Total</td>
        <td class="fonts">148</td>
        <td class="fonts">200</td>
        <td class="fonts">1184</td>
        <td class="fonts">1600</td>
        <td class="fonts">1208</td>
        <td class="fonts">918</td>
    </tr>
</table>

<p><sub>(The GIFs are direct 2x scale, so I just split the frames and used those to measure the pixels :D)</sub></p>

<h1>Conclusions</h1>

<p>It's not quite as apples-to-apples, but English taking 200 characters to convey what Japanese does in 148 is indicative of a larger trend we see that causes a lot of trouble when it comes to the actual storage of English text when memory is limited... This is a storage problem though, and not one of actual visual space. If we're willing to spend the computation to render English text dynamically, then we can fit as much, if not more information within the same visual space by using a variable-width font!</p>

<p>Now if we could just figure out a way to do it in a way that didn't involve needing to draw text dynamically while maintaining the same text storage efficiency... I suppose that's a deep dive for another time, or research for someone smarter than me to get into. For now, at least, I'll focus on shoving VWF into as many projects as I can.</p>

<h1>Some final personal notes</h1>

<p>One of my New Years' resolutions was to write a bit more and to get generally better at articulating my thoughts. It has a few other nice benefits too...</p>

<ul>
<li>I finally get to live out the HTML/CSS dream I missed because I scoffed at MySpace and personal blogs in my teenage years</li>
<li>It's quite therapeutic to put things to paper and/or keyboard</li>
<li>Writing things down in this format really lets me dig into topics I wouldn't really spend as much time on, especially with things like gathering stats!</li>
</ul>

<p>Also, since I'm starting to forget more things recently, I figured it might be a good time to start really investing in archiving whatever knowledge I've accumulated... if for no one else's benefit but my future own.</p>

<p>So that being said, thanks for reading!</p>
]]></description>
<link>https://www.vxyz.me/00002.html</link>
<guid>https://www.vxyz.me/00002.html</guid>
<pubDate>Wed, 01 Jan 2025 13:29:41 -0800</pubDate>
</item>
<item>
<title>Playing with Power... PC</title>
<description><![CDATA[<p>I bought a cheap 2004 iBook G4 for like 35$ and wanted to see if I could bring some life to it for something like no-distraction Gameboy development or just writing stuff. For how old it is, OS X 10.4.11 (Tiger) runs pretty well... but not well enough for me to try building complex things on it (a Gameboy toolchain is about it). So, I figured my project for the week would be to see what the state of cross-compiling a modern toolchain for a >20 year old system would look like.</p>

<p>The original verison of this post from yesterday actually relied on some ancient binaries from old versions of XCode, but thanks to the dedicated efforts of several people in the last decade, we have a fairly recent ld we can build on anything with Clang 10 or higher and some useful information.</p>

<p>For reference, you can see the original markdown for that post <a href="https://github.com/VariantXYZ/blog.md/blob/5a1277e651acd204fd1e182680be3a698fea241a/posts/00003_Playing_with_Power..._PC/post.md">here</a>.</p>

<p>It's pretty cool how many people still seem to want to keep these old things alive.</p>

<p>Anyway, here's what I've accumulated to build the rgbds toolchain for powerpc-apple-darwin8.</p>

<p>My updated Dockerfile for different versions of GCC and SDKs can be found <a href="https://github.com/VariantXYZ/gcc-powerpc-apple-darwin8">here</a>.</p>

<p><style>
pre {
    display: block;
    white-space: pre-wrap;
    word-wrap: break-word; 
    overflow-wrap: break-word; 
    font-family: monospace;
    background: lightgray;
}
</style></p>

<h2>References</h2>

<ul>
<li><a href="https://maniacsvault.net/articles/powerpccross">Bluzt3's Blog</a></li>
<li><a href="https://wiki.osdev.org/GCC_Cross-Compiler">OSDev Wiki</a></li>
<li><a href="https://github.com/tpoechtrager/cctools-port">OSXCross/cctools-port</a></li>
</ul>

<h2>Pre-requisites</h2>

<ul>
<li>clang > 10</li>
<li>CMake > 3.4.3</li>
<li>Make > 4</li>
<li>Whatever GCC might need (I needed to do <code>brew install texinfo</code>)</li>
<li><code>llvm-devel</code> if you want LTO support (recommend it)</li>
</ul>

<p>The following instructions all operate based on the environment variables below and from a root directory.</p>

<p>Here's the set of installed binaries on Ubuntu 24.04</p>

<pre><code>apt-get update -q &amp;&amp; 
    apt-get install -y 
    cmake 
    ninja-build 
    build-essential 
    clang 
    llvm-dev 
    git 
    python3 
    wget 
    flex 
    texinfo 
    file 
    autoconf 
    libssl-dev 
    libz-dev 
    libtool-bin 
    &amp;&amp; apt-get autoremove -y --purge 
    &amp;&amp; apt-get clean -y 
    &amp;&amp; rm -rf /var/lib/apt/lists/*
</code></pre>

<h2>Environment</h2>

<pre><code>export ROOT_DIR="$(pwd)"
export TARGET_PREFIX="$(pwd)/install/target"
export TARGET=powerpc-apple-darwin8
export MAC_SDK_VERSION=MacOSX10.4u
export MACOSX_PPC_DEPLOYMENT_TARGET=10.4
mkdir -p "$TARGET_PREFIX"
</code></pre>

<p><strong>NOTE</strong>: We are using the 10.4 SDK but will need to rebuild crt1.o. This is due to the <a href="https://github.com/tpoechtrager/osxcross/issues/50#issuecomment-149013354">issue with 10.4's crt1.o</a>. 10.5 should theoretically work too.</p>

<h2>cctools</h2>

<p>Reference this long discussion <a href="https://github.com/tpoechtrager/cctools-port/issues/119">here</a> where a lot of people chime in on how to get this all working. Or don't, and just note the final results below, that's cool too.</p>

<h3>dsymutil</h3>

<p>Not included as part of the rest of cctools, so we'll quickly build llvm 7.1.1, which is the last version with powerpc-apple-darwin8 target support with dsymutil.</p>

<p>This is easily the longest part of the whole process because apparently we need to build a ton of LLVM before we can build dsymutil...</p>

<pre><code>mkdir -p $ROOT_DIR/llvm-project &amp;&amp; 
    cd $ROOT_DIR/llvm-project &amp;&amp; 
    git init &amp;&amp; 
    git remote add origin https://github.com/llvm/llvm-project.git &amp;&amp; 
    git fetch --depth 1 origin 4856a9330ee01d30e9e11b6c2f991662b4c04b07 &amp;&amp; 
    git checkout FETCH_HEAD

mkdir -p $ROOT_DIR/build/target/llvm-project &amp;&amp; 
cd $ROOT_DIR/build/target/llvm-project &amp;&amp; 
CC=clang CXX=clang++ cmake -G Ninja $ROOT_DIR/llvm-project/llvm 
  -DCMAKE_BUILD_TYPE=Release 
  -DLLVM_TARGETS_TO_BUILD="PowerPC" 
  -DLLVM_ENABLE_ASSERTIONS=OFF &amp;&amp; 
ninja dsymutil &amp;&amp; 
mkdir -p $TARGET_PREFIX/bin &amp;&amp; 
cp bin/dsymutil $TARGET_PREFIX/bin/$TARGET-dsymutil &amp;&amp; 
cd $ROOT_DIR &amp;&amp; 
rm -rf $ROOT_DIR/build/target/llvm-project &amp;&amp; 
rm -rf $ROOT_DIR/llvm-project
</code></pre>

<h3>ld, as, ar, lipo, nm, ranlib</h3>

<pre><code>mkdir -p $ROOT_DIR/cctools-port &amp;&amp; 
cd $ROOT_DIR/cctools-port &amp;&amp; 
git init &amp;&amp; 
git remote add origin https://github.com/tpoechtrager/cctools-port.git &amp;&amp; 
git fetch --depth 1 origin 6694f27d56923e64e6190c8d3eb149413768e9b7 &amp;&amp; 
git checkout FETCH_HEAD &amp;&amp; 
cd cctools &amp;&amp; 
./autogen.sh

mkdir -p $ROOT_DIR/build/target/cctools-port &amp;&amp; 
cd $ROOT_DIR/build/target/cctools-port &amp;&amp; 
$ROOT_DIR/cctools-port/cctools/configure CC=clang CXX=clang++ --prefix="$TARGET_PREFIX" --target=$TARGET &amp;&amp; 
make -j2 &amp;&amp; 
make install -j &amp;&amp; 
mkdir -p $TARGET_PREFIX/$TARGET/bin &amp;&amp; 
for i in ld ar as lipo nm ranlib strip dsymutil; do 
  ln -s "$TARGET_PREFIX/bin/$TARGET-$i" "$TARGET_PREFIX/$TARGET/bin/$i"; 
done &amp;&amp; 
cd $ROOT_DIR &amp;&amp; 
rm -rf $ROOT_DIR/build/target/cctools-port &amp;&amp; 
rm -rf $ROOT_DIR/cctools-port
</code></pre>

<p>(Note we also symlink for convenience here)</p>

<h2>MacOSX SDK</h2>

<pre><code>wget https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/$MAC_SDK_VERSION.sdk.tar.xz
tar xf ./$MAC_SDK_VERSION.sdk.tar.xz -C $TARGET_PREFIX
</code></pre>

<p>We explicitly copy it into the prefix so it should benefit from the <code>--with-sysroot</code> option, at least according to the GCC docs:
<code>If the specified directory is a subdirectory of ${exec_prefix}, then it will be found relative to the GCC binaries if the installation tree is moved.</code></p>

<p>We then also need to extract the ppc binaries out of the universal binaries, allowing us to actually link against them without worrying about universal binary support. Note that we don't want to hit the <code>ppc7400</code> binaries, since those are for 10.5 and the goal here is just for a Tiger focused SDK.</p>

<pre><code>cd $TARGET_PREFIX/$MAC_SDK_VERSION.sdk/usr/lib
for i in **/*.dylib **/*.a **/*.o; do
  if file "$i" | grep -q "for architecture ppc)"; then
    mv $i $i.universal
    $TARGET_PREFIX/bin/$TARGET-lipo -thin ppc $i.universal -output $i
  elif file "$i" | grep -q "for architecture ppc7400)"; then
    mv $i $i.universal
    $TARGET_PREFIX/bin/$TARGET-lipo -thin ppc7400 $i.universal -output $i
  fi
done
cd -
</code></pre>

<h2>Building gcc</h2>

<p>Some minor modifications to libgcc's dynamic library generation. Since it calls <code>lipo</code> to generate universal binaries, which our cctools-built linker doesn't support, I've created a simple patch to skip calling it when there's only one architecture.</p>

<pre><code>mkdir -p gcc
cd gcc
git init
git remote add origin git@github.com:VariantXYZ/gcc-13-branch.git
git fetch --depth 1 origin 908dbc96f1271f995759c87fc9d32879d6f49756
git checkout FETCH_HEAD
./contrib/download_prerequisites
cd -
</code></pre>

<h3>Just the compiler</h3>

<p>Note we make some hard-coded configuration settings to avoid gcc making assumptions about as and ld features we don't have. This is also in that GitHub issue discussion linked above.</p>

<pre><code>mkdir -p $ROOT_DIR/build/target/gcc &amp;&amp; 
cd $ROOT_DIR/build/target/gcc &amp;&amp; 
echo "" &gt; config.site-$TARGET &amp;&amp; 
echo "gcc_cv_as_mmacosx_version_min=no" &gt;&gt; config.site-$TARGET &amp;&amp; 
echo "gcc_cv_as_darwin_build_version=no" &gt;&gt; config.site-$TARGET &amp;&amp; 
echo "gcc_cv_ld64_demangle=0" &gt;&gt; config.site-$TARGET &amp;&amp; 
echo "gcc_cv_ld64_platform_version=0" &gt;&gt; config.site-$TARGET &amp;&amp; 
CONFIG_SITE=$ROOT_DIR/build/target/gcc/config.site-$TARGET $ROOT_DIR/gcc/configure CC=clang CXX=clang++ --disable-nls --disable-multilib --enable-languages=c,c++,lto --with-dwarf2 --prefix="$TARGET_PREFIX" --target=$TARGET --with-sysroot="$TARGET_PREFIX/$MAC_SDK_VERSION.sdk" CXXFLAGS_FOR_TARGET="-O2 -g -mmacosx-version-min=$MACOSX_PPC_DEPLOYMENT_TARGET" CFLAGS_FOR_TARGET="-O2 -g -mmacosx-version-min=$MACOSX_PPC_DEPLOYMENT_TARGET" LDFLAGS_FOR_TARGET="-O2 -g -mmacosx-version-min=$MACOSX_PPC_DEPLOYMENT_TARGET" --disable-bootstrap &amp;&amp; 
make all-gcc -j2 &amp;&amp; 
make install-gcc -j
</code></pre>

<p>Before we get back to gcc, we need to go rebuild crt1.o as mentioned above.</p>

<h3>Rebuilding Apple crt1.o</h3>

<p>This one is a bit hacky compared to the rest, but we only need to rebuild one part of Apple's runtime libraries (crt1.o). This is only necessary if we're using the 10.4u SDK, at any rate.</p>

<pre><code>mkdir -p csu
cd csu
git init
git remote add origin git@github.com:VariantXYZ/Csu.git
git fetch --depth 1 origin 06967ab403a7a04e30e2f32479285d68152cedd2
git checkout FETCH_HEAD
cd -
</code></pre>

<p>(For the record, I just renamed files to let GCC handle assembly preprocessing, otherwise the cctools assembler has trouble)</p>

<pre><code>cd csu
make CC=$TARGET_PREFIX/bin/powerpc-apple-darwin8-gcc ARCH_CFLAGS="-arch ppc -D__private_extern__= -isysroot $TARGET_PREFIX/$MAC_SDK_VERSION.sdk" ./crt1.v1.o
mv ./crt1.v1.o $TARGET_PREFIX/$MAC_SDK_VERSION.sdk/usr/lib/crt1.o
cd -
</code></pre>

<h3>The rest of the GCC runtime/libraries</h3>

<pre><code>cd build/target/gcc
make -j &amp;&amp; 
make install -j
cd -
</code></pre>

<p>...and that's it, that's the toolchain. Well, the target toolchain anyway, we still need the GBDev one :^).</p>

<h2>Building rgbds for powerpc-apple-darwin8</h2>

<p><code>CFLAGS</code> and <code>CXXFLAGS</code> must include <code>-static-libstdc++</code> and <code>-static-libgcc</code> since we won't have dynamic libraries on the target, but other than that, it should be feasible to just reference <code>CC</code> and <code>CXX</code> to the powerpc toolchains. Note we're still operating in the same directory.</p>

<h3>libpng</h3>

<p>We need libpng for rgbgfx, so we'll build it first and install it into our prefix.</p>

<pre><code>mkdir -p libpng
cd libpng
git init
git remote add origin git@github.com:pnggroup/libpng.git
git fetch --depth 1 origin f753baae52e1f0fd5451c25de8f8361ec5aea95f
git checkout FETCH_HEAD
cd -

mkdir -p build/target/libpng
cd build/target/libpng
PATH=$TARGET_PREFIX/bin:$PATH LDFLAGS="-static-libstdc++ -static-libgcc" CXX=$TARGET_PREFIX/bin/$TARGET-g++ CC=$TARGET_PREFIX/bin/$TARGET-gcc $ROOT_DIR/libpng/configure --prefix=$TARGET_PREFIX/$TARGET --host=$TARGET
PATH=$TARGET_PREFIX/bin:$PATH make -j
PATH=$TARGET_PREFIX/bin:$PATH make install -j
cd -
</code></pre>

<h3>rgbds</h3>

<p>Working on tag v0.9.0 (a good way to test that C++20 works). PNG should be in our search path automatically, but we need to make sure it doesn't use the host-installed libpng.</p>

<pre><code>mkdir -p rgbds
cd rgbds
git init
git remote add origin git@github.com:gbdev/rgbds.git
git fetch --depth 1 origin d63955eccd7aa69794960a626144ea247d638957
git checkout FETCH_HEAD

mkdir -p $TARGET_PREFIX/$TARGET/deploy
PATH=$TARGET_PREFIX/$TARGET/bin:$PATH make install -j LDFLAGS="-static-libstdc++ -static-libgcc" PNGCFLAGS="" PNGLDFLAGS="-lpng" PNGLDLIBS="" CXX=$TARGET_PREFIX/bin/$TARGET-g++ CC=$TARGET_PREFIX/bin/$TARGET-gcc CXXFLAGS="-D__STDC_FORMAT_MACROS" PREFIX=$TARGET_PREFIX/deploy
</code></pre>

<p>Note:
* We need to add <code>-D__STDC_FORMAT_MACROS</code> when using g++ in our case since <code>inttypes.h</code> will not enable certain macros otherwise (C99 locks it behind a macro, C++ doesn't seem to care)
* We specify the path to make sure <code>strip</code> is called such that the <code>install</code> utility can use it, instead of the system strip</p>

<p>Anyway, after all this, you can verify it with <code>file rgbasm</code>:</p>

<pre><code>% file rgbasm
rgbasm: Mach-O executable ppc
</code></pre>

<p>Horray! We actually have to more thoroughly test it... but maybe that's a problem for another day.</p>
]]></description>
<link>https://www.vxyz.me/00003.html</link>
<guid>https://www.vxyz.me/00003.html</guid>
<pubDate>Mon, 20 Jan 2025 01:58:42 -0800</pubDate>
</item>
<item>
<title>So much done, so little accomplished...</title>
<description><![CDATA[<p>Well, I wanted to try making a post once a month but lost track of time, so that's one New Years' resolution broken quite quickly. I was actually doing things though! Let me explain!</p>

<h2>Making 2025 the year of productive PowerPC usage</h2>

<p>If you recall <a href="00003.html">my earlier post</a>, I had gotten GCC 14.2 building things for Mac OS X 10.4 PowerPC (darwin8). Of course, after going through all that trouble, I did want to actually use the thing.</p>

<p>I figured an old PPC G4 could still find life as a GameBoy development machine, so I got to work trying to build everything necessary to checkout a repository, build a GB ROM, and actually debug and test it. </p>

<p>This meant building:</p>

<ul>
<li>rgbds</li>
<li>Python 3</li>
<li>git with openssl support</li>
<li>An emulator</li>
</ul>

<p>Simple enough, right? Well, sorta. Turns out, all software is just built on top of other software so there's quite a bit of work to do...</p>

<p><img src="dependency_2x.png" alt="xkcd" title="An xkcd for everything" /></p>

<p>Here's a glimpse at what it takes to build Git, for example:</p>

<p><img src="build_git.png" alt="Building git" title="GitHub is not very efficient" /></p>

<p><sub>(I wish GitHub would let me properly re-use build flows in a sane way)</sub></p>

<p>I won't bore you guys with all the details, but there was a lot of random little changes in various projects and a handful of forks and research. </p>

<p>All of that work can be found in the GitHub Actions <a href="https://github.com/VariantXYZ/gbdev-powerpc-apple-darwin8">here</a> and the forks I reference in them.</p>

<p>Everything culminated in being able to build and run the Medarot 3 patch at a glacial framerate:</p>

<p><blockquote class="bluesky-embed" data-bluesky-uri="at://did:plc:bxec6nf4fgw2njjhxbwhsord/app.bsky.feed.post/3lie2fcysqc2n" data-bluesky-cid="bafyreiaqnv2qh242pywak4zl3hx4ioxyflsfxtlo7cnjcdtkuctpgpyhke" data-bluesky-embed-color-mode="system"><p lang="en">Well, patched up enough of SDL 2.0.3 and added some stuff from 2.0.4 to build SameBoy. </p>

<p>If you listen closely, you can hear Ikki&#x27;s voice played at 5 Hz.<br><br><a href="https://bsky.app/profile/did:plc:bxec6nf4fgw2njjhxbwhsord/post/3lie2fcysqc2n?ref_src=embed">[image or embed]</a></p>&mdash; Variant (<a href="https://bsky.app/profile/did:plc:bxec6nf4fgw2njjhxbwhsord?ref_src=embed">@vxyz.me</a>) <a href="https://bsky.app/profile/did:plc:bxec6nf4fgw2njjhxbwhsord/post/3lie2fcysqc2n?ref_src=embed">February 16, 2025 at 9:49 PM</a></blockquote><script async src="https://embed.bsky.app/static/embed.js" charset="utf-8"></script></p>

<p>...Alright, so we still have some work to do here, but it's a good(?) transition into what's been eating up my time more recently.</p>

<h2>Wonder what it'd take to write an emulator?</h2>

<p>SameBoy is well known as being a highly accurate GB/GBC emulator that's fairly feature rich, but... it's not really designed nor optimized for a single-thread machine from 2003 that only supports OpenGL 1.1. The video above showcases a pretty common issue I've had.</p>

<p>Other emulators exist, but they either opt to drop accuracy for speed (so, not great for development and they usually don't have debugging features), or are even worse performing for a richer feature set. I even had Calindro, the Emulicious dev, reach out and had me test some builds but to no avail. Nothing really achieves a practical debugging experience on a Mac OS X 10.4 PPC that I could find...</p>

<p>So, of course, here I am with a pretty unique problem statement and set of resourcees, and I figure... if I've got a C++ 20 compiler and an understanding of the exact workflow I'm trying to build a tool for, maybe I can start writing an emulator with the features I need myself? It would also finally give me an opportunity to play around with C++20 and I could probably spin that as some form of professional development... at least, that's what I told myself.</p>

<p>The project, aptly named <a href="https://github.com/VariantXYZ/PowerGB/tree/add_instructions">PowerGB</a>, is still a work-in-progress. I've been finally getting to the stage of adding instruction parsing after working on it on-and-off after work. If you're wondering why it's taking me so long, it's because I keep finding new things in C++20 that make me interested and I waste days doing things like <a href="https://github.com/VariantXYZ/PowerGB/blob/main/src/common/result.hpp">writing a comprehensive result wrapper</a> instead of doing actual work.</p>

<p>Though, to be honest, I'll probably put this on hold because there are other things I'd like to get done...</p>

<h2>Medabots GBC titles before 2030!?</h2>

<p>Yeah, the Medabots GBC titles are still a slow work-in-progress... but we're still making progress.</p>

<h3>Medabots 3 "US Localized" Version</h3>

<p>andwhyisit handled some of the graphics work for the Medabots 3 US-English localization patch and I finally got around to writing that text replacement script, so the first (unfinished) nightly release of tr_EN-US is <a href="https://github.com/Medabots/medarot3/releases/tag/tr_EN-US%2Bnightly.20250323">here</a>.</p>

<p><style>
span.medabots img
{
    max-width: 49%;
    height: auto;
}
</style></p>

<p><span class="medabots"><img src="medabots3_rubberobo.png" alt="Medabots 3 Rubberobo" title="Rubberobo Gang" /> <img src="medabots3_kwg.png" alt="Medabots 3 Kuwagata" title="Kuwagata Version" /></span>
<sub>Poor Shrimplips is almost entirely covered by the text :(</sub></p>

<h3>The other GBC titles</h3>

<p>The development aside, the 4th title is about 40% more text than the 3rd, so I have a feeling I might not be the major bottleneck... eventually anyway.</p>

<p>I think the 5th title should be a bit smaller, at least.</p>

<p>At the rate we're going it might be cutting it close to get it all done by 2030, but uh, I'm sure we'll be fine if I don't get distracted <a href="https://github.com/VariantXYZ/sakura-wars-gb2/tree/master">by</a> <a href="https://github.com/VariantXYZ/dragon-warrior-3-gbc">other</a> <a href="https://github.com/VariantXYZ/metamode/tree/dump_dialog">projects</a>.</p>

<h2>Work and other things</h2>

<p>My job tend to be quite technically challenging so my brain wants to shut-off at times. I suspect things might get easier in the coming months, but phew, it's a real motivator to try and save up as much as I can to retire early so I can devote more time into projects and other things... alas, if only it were that simple.</p>

<h3>Games! Actually playing them!</h3>

<p>In the last several years, investing any amount of time into a title has been pretty difficult. I beat Radiant Historia over the course of 2 years, Dragon Quest 11 took me a year, and even now I'm finally approaching the end of the DQ3 remake at about 40 hours. I'm thankful that I'm finding some time to play, but phew, 40 hours really feels like the limit of a reasonable sink... maybe I'm just getting old.</p>

<p>That being said, DQ3's Recall mechanic being streamlined is such a nice feature. I wish every JRPG had a button I could press to let me remember NPC dialog at any moment. It's such a nice touch, and probably my favorite feature of DQ3 in general.</p>

<h2>Finishing up</h2>

<p>Anywho, I guess we'll all see how things shape up in the coming year. At a later date, maybe I'll do some more technical deep dives... but for that, I might need to dive in a bit deeper myself first.</p>
]]></description>
<link>https://www.vxyz.me/00004.html</link>
<guid>https://www.vxyz.me/00004.html</guid>
<pubDate>Sat, 22 Mar 2025 22:29:06 -0700</pubDate>
</item>
<item>
<title>PowerGB DevLog 1 - The C in C++ stands for Crime</title>
<description><![CDATA[<p>First post of 2026! (Albeit a bit later than I expected...) </p>

<p>I've been feeling pretty mentally exhausted from work and life things, and so the only projects I've really put time into have been ones that are more creative than investigative. That is to say, I haven't felt like reverse engineering things for a little bit but I'm sure I'll get back into it soon.</p>

<p>On the creative side though, my little pet GB emulator project <a href="https://github.com/VariantXYZ/PowerGB/">PowerGB</a> has been an exercise in seeing how far I can get pure portable C++20 to go.</p>

<h2>A GameBoy Emulator should have a Philosophy</h2>

<p>I imagine for a lot of people, a GameBoy emulator is usually a really fun sounding project. It's a well-documented system with a large support community, a ton of people who've gone through the same struggles you'll run into, and a lot of open-source working examples to reference. It's an absolutely phenomenal platform for development experiments and learning.</p>

<p>You'll find implementations that are highly accurate down to the CPU tick, ones that provide Python interfaces for automation, and even things that do JIT and static-based recompilation. </p>

<p>So given what's already out there, I figured I wanted to approach this with my own philosophy as I study the newer features of C++, originally propagated by my earlier <a href="./00003.html">post</a> where I documented my adventures getting a C++20-compatible cross-compiler working on OSX Tiger. </p>

<h3>As close as we can to a consteval world</h3>

<p>As I went through thinking and defining various parts of the process, which I'll go into more detail below, I attempted to push as much of the work as possible to compile-time evaluation and correctness, even if it meant fighting the language a little. This meant extensive use of <code>static_assert</code> to make sure things were being evaluated at compile-time.</p>

<p>The easier we can prove to a compiler that something can be optimized out, the better.</p>

<h2>Life's no fun without a few complications</h2>

<p>I think C++ introduces opportunities for overengineering for meager advantages a lot, and really emphasizes the fun in the journey rather than the destination. I've really come to embrace this in personal projects because no one'll fire me for taking too long thinking about minor things. I wonder how people get away with reimplementing boost in production code though...</p>

<h3>Debugging sucks, so let's make sure error scenarios are clear</h3>

<p>I spent a lot of time putting together a pretty flexible results system within a single header, a little like Rust's own <code>Result&lt;...&gt;</code> type.</p>

<p>It works like this:
* A <code>Result</code> is defined via a string literal description and whether or not it should be considered a success
* A <code>ResultSet</code> is a wrapper around several results and a particular object (a return value)</p>

<p>It's possible to cast a <code>ResultSet</code> of one function into another as long as the target result set can handle all the possible results of the source set.</p>

<p>So every single result is expected to be explicitly handled, or caught at compile-time when it's not. The results themselves have string literals that can be propagated up to callers.</p>

<p>So you can go from one result type to another while preserving the underlying Result value, as long as the states can be determined at compile-time:</p>

<pre><code>{
    using ResultSetTestInt   = ResultSet&lt;int, ResultSuccess&gt;;
    using ResultSetTestFloat = ResultSet&lt;float, ResultSuccess, ResultFailure&gt;;

    int  a                   = 255;
    auto resultInt           = ResultSetTestInt::DefaultResultSuccess(a);
    TEST_CHECK(static_cast&lt;int&gt;(resultInt) == 0xFF);

    auto resultFloat = static_cast&lt;ResultSetTestFloat&gt;(resultInt);
    TEST_CHECK(static_cast&lt;float&gt;(resultFloat) == 255.0f);
}
</code></pre>

<p>The caller will (must) always know what it's calling can actually return. No offline integer-to-string lookups or dynamic exception handling.</p>

<h3>Basic Building Blocks</h3>

<p>So in another fun over-complication, I decided to think about how to represent the underlying register types.</p>

<p>The GameBoy has a register file that contains a handful of registers that can also be referenced in pairs, including:
* An 8-bit accumulator register <code>A</code> and "4-bit" (8 with the lower 4 bits always 0) flag register <code>F</code>
* Several registers accessible as 8-bit pairs or a single 16-bit register (<code>BC</code> or <code>B</code> and <code>C</code>, <code>DE</code> or <code>D</code> and <code>E</code>, <code>HL</code> or <code>H</code> and <code>L</code>)
* A program counter and stack pointer, each accessible as 16-bit registers (<code>PC</code> and <code>SP</code>, respectively)</p>

<p>Each register has different access expectations and would benefit from slightly different access patterns, with the flexibility to be used in multiple configurations. While it's pretty trivial to just create some <code>uint16_t</code> values and some neat little bitmasking functions, that's not what I'm about. Enter the <code>Block</code> class: a representation of data that's meant to emphasize specific access patterns while allowing for others.</p>

<p>For example, given a template <code>Block&lt;Size, AccessGranularity&gt;</code>, we can have each register above defined like so:</p>

<pre><code>//// Accumulator
Block&lt;8, 8&gt; _A; // 8-bit register that's expected to be accessed as 8-bit

//// Flag
Block&lt;8, 4&gt; _F; // 8-bit register expected to be accessed by Nibbles

//// General purpose
Block&lt;16, 8&gt; _BC; // 16-bit register expected to be accessed in 8-bit chunks
Block&lt;16, 8&gt; _DE;
Block&lt;16, 8&gt; _HL;

// Program counter
Block&lt;16, 16&gt; _PC; // 16-bit register expected to be accessed as 16-bit

// Stack pointer
Block&lt;16, 16&gt; _SP;
</code></pre>

<p>Allowing for access to each of these registers with varying access patterns (e.g., a 4-bit <code>Nibble</code>, an 8-bit <code>Byte</code>, or a 16-bit <code>Word</code>) but prioritizing the provided access granularity. With some good compile-time definitions in release builds, I suspect we can make this into the zero-cost abstraction meme.</p>

<h3>A Registry in Many Parts</h3>

<p>The last bit for this particular update is my dream of making a compile-time registry of instruction handlers, in several files for organization.</p>

<p>To explain what that means, first let's get some points about instructions:
* Every instruction can just be broken down into a set of operands and operations on the memory and CPU state (for simplicity, I just map things through a single memory map for everything)
* Instruction operations can generally be categorized (loads, arithmetic, logic, etc...)
* Each instruction can map to an opcode (1 byte or 2 bytes) and some variable number of operands (0 to 2 bytes)</p>

<p>So we have instructions like <code>NOP</code>, <code>LD [HL], A</code> (load the value from A into the memory address represented by <code>HL</code>), and <code>INC BC</code> (increment <code>BC</code>). </p>

<p>Referencing <a href="https://github.com/Gekkio/gb-ctr">gekkio's technical reference</a>, it's possible to get the general timing and behavior of all the instructions as well. We even have some <a href="https://github.com/SingleStepTests/sm83/">tests based on the Ares emulation core</a> we can use to validate them!</p>

<p>The intuitive approach to this would be to have some functions for each instruction and maybe use templates to reduce boilerplate, and then finally just have a single large array to 'decode' opcodes.</p>

<p>Seems pretty straightforward... but also feels kinda boring. </p>

<p>Firstly, I <em>don't want to keep track of a big array</em> and I know with C++ I can define an array at compile-time pretty easily with something like:</p>

<pre><code>static constexpr auto CreateCallbackMap() noexcept
{
    // An array of callbacks mapped to the bytes
    std::array&lt;std::size_t (*)(MemoryMap&amp;) noexcept, 0xFF + 1&gt; callbacks{nullptr};

    // Fill the callback array somehow

    return callbacks;
}
</code></pre>

<p>Second, I want to organize each instruction by category in separate files so I can define category-specific operations neatly.</p>

<p>Finally, I want all of this to happen at compile-time so no shenanigans like a static constructor to handle registration.</p>

<p>Given the above conditions, the obvious problem is that "creating a registry at compile-time" means somehow maintaining state at compile-time... luckily, there is a solution! One that's <em>technically</em> within the bounds of the language and requires careful use to not violate the one-definition rule. Enter: <code>friend-njection</code> and <code>Argument-Dependent Lookup</code> (explained well in <a href="https://stackoverflow.com/questions/72598498/behaviour-of-friend-function-template-returning-deduced-dependent-type-in-class">this StackOverflow post</a>).</p>

<p>To not bore you with many details, the actual registry header is <a href="https://github.com/VariantXYZ/PowerGB/blob/c72b987418c6bdd5e9cedad3d6cb2b14a566f62e/src/common/registry.hpp">here</a>. </p>

<p>Effectively, we have an <code>InstructionDecoder</code> class template used that ties an opcode with functions and metadata (e.g., CPU ticks) and <em>also</em> appends to a registry. </p>

<p>The registry itself maintains a callback map that simply gets filled by:</p>

<pre><code>((callbacks[Decoders::Opcode] = &amp;Decoders::Execute), ...);
</code></pre>

<p>Then each instruction category can be defined in separate files and as long as they end up in the same translation unit (e.g., with <code>cpu.cpp</code>), we'll have a compile-time registry defined with everything in a separate file!</p>

<h2>Marching onwards</h2>

<p>There were definitely a few things I skipped above, but those were the most interesting I think. Using known tests, I've been able to implement instructions without much trouble, albeit slowly and whenever I find time. It doesn't help that all of this work is happening on my old XPS 13 from 2016 with 8 GB of RAM. I might do another post later about my adventures in trying to speed up build times (those compile-time shenanigans definitely have a cost somewhere...).</p>

<p>In personal projects, especially ones related to reverse engineering, I've generally learned that there's a lot of value in taking the time to understand problems and build a solid foundation. Being able to take each step and validate it is a fantastic privilege that not many fields get to experience, so it feels a bit wasteful to not do it when I can. </p>

<p>My old man philosophy aside, this has been a really fun project so far and I'm looking forward to researching and implementing the clock and interrupt behavior next, and then graphics!</p>
]]></description>
<link>https://www.vxyz.me/00005.html</link>
<guid>https://www.vxyz.me/00005.html</guid>
<pubDate>Mon, 09 Feb 2026 21:00:16 -0800</pubDate>
</item>
</channel>
</rss>