diff --git a/blog/super-bootable-64-2020-05-06.markdown b/blog/super-bootable-64-2020-05-06.markdown
new file mode 100644
index 0000000..5763100
--- /dev/null
+++ b/blog/super-bootable-64-2020-05-06.markdown
@@ -0,0 +1,378 @@
+---
+title: Super Bootable 64
+date: 2020-05-06
+series: howto
+tags:
+ - witchcraft
+ - supermario64
+ - nixos
+---
+
+# Super Bootable 64
+
+[Super Mario 64][sm64] was the launch title of the [Nintendo 64][n64] in 1996.
+This game revolutionized an entire generation and everything following it by
+delivering fast, smooth and fun 3d platforming gameplay to gamers all over the
+world. This game is still played today by speedrunners, who do everything from
+beating it while collecting every star, the minimum amount of stars normally
+required, 0 stars and [without pressing the A jump button][wfrrpannenkoek].
+
+[sm64]: https://en.wikipedia.org/wiki/Super_Mario_64
+[n64]: https://en.wikipedia.org/wiki/Nintendo_64
+[wfrrpannenkoek]: https://youtu.be/kpk2tdsPh0A
+
+This game was the launch title of the Nintendo 64. As such, the SDK used to
+develop it was pre-release and [had an optimization bug that forced the game to
+be shipped without optimizations due to random crashiness issues][mvgo0] (watch
+the linked video for more information on this than I can summarize here).
+Remember that the Nintendo 64 shipped games on write-once ROM cartridges, so any
+bug that could cause the game to crash randomly was fatal.
+
+[mvgo0]: https://youtu.be/NKlbE2eROC0
+
+When compiling something _without_ optimizations, the output binary is
+effectively a 1:1 copy of the input source code. This means that exceptionally
+clever people could theoretically go in, decompile your code and then create
+identical source code that could be used to create a byte-for-byte identical
+copy of your program's binary. But surely nobody would do that, that would be
+crazy, wouldn't it?
+
+

+
+Someone did. The fruits of this effort are available [here][sm64dc]. This was
+mostly a proof of concept and is a masterpiece in its own right. However,
+because it was decompiled, this means that the engine itself could theoretically
+be ported to run on any other platform such as Windows, Linux, the Nintendo
+Switch or even a [browser][sm64browser].
+
+[sm64dc]: https://github.com/n64decomp/sm64
+[sm64browser]: https://froggi.es/mario/
+
+[Someone did this][sm64pcnews] and ended up posting it on 4chan. Thanks to a
+friend, I got my hands on the Linux-compatible source code of this port and made
+an archive of it [on my git server][sm66pcsauce]. My fork of it has only
+minimal changes needed for it to build in NixOS.
+
+[sm64pcnews]: https://www.videogameschronicle.com/news/a-full-mario-64-pc-port-has-been-released/
+[sm66pcsauce]: https://tulpa.dev/saved/sm64pc
+
+[nixos-generators][nixosgenerators] is a tool that lets you create custom NixOS
+system definitions based on a NixOS module as input. So, let's create a bootable
+ISO of Super Mario 64 running on Linux!
+
+[nixosgenerators]: https://github.com/nix-community/nixos-generators
+
+## Setup
+
+You will need an amd64 Linux system. NixOS is preferable, but any Linux system
+should _theoretically_ work. You will also need the following things:
+
+- `sm64.us.z64` (the release rom of Super Mario 64 in the US version 1.0) with
+ an sha1 sum of `9bef1128717f958171a4afac3ed78ee2bb4e86ce`
+- nixos-generators installed (`nix-env -f
+ https://github.com/nix-community/nixos-generators/archive/master.tar.gz -i`)
+
+So, let's begin by creating a folder named `boot2sm64`:
+
+```console
+$ mkdir ~/code/boot2sm64
+```
+
+Then let's create a file called `configuration.nix` and put some standard
+boilerplate into it:
+
+```nix
+# configuration.nix
+
+{ pkgs, lib, ... }:
+
+{
+ networking.hostName = "its-a-me";
+}
+```
+
+And then let's add [dwm][dwm] as the window manager. This setup will be a little
+bit more complicated because we are going to need to add a custom configuration
+as well as a patch to the source code for auto-starting Super Mario 64. Create a
+folder called `dwm` and run the following commands in it to download the config
+we need and the autostart patch:
+
+[dwm]: https://dwm.suckless.org/
+
+```console
+$ mkdir dwm
+$ cd dwm
+$ wget -O autostart.patch https://dwm.suckless.org/patches/autostart/dwm-autostart-20161205-bb3bd6f.diff
+$ wget -O config.h https://gist.githubusercontent.com/Xe/f5fae8b7a0d996610707189d2133041f/raw/7043ca2ab5f8cf9d986aaa79c5c505841945766c/dwm_config.h
+```
+
+And then add the following before the opening curly brace:
+
+```nix
+
+{ pkgs, lib, ... }:
+
+let
+ dwm = with pkgs;
+ let name = "dwm-6.2";
+ in stdenv.mkDerivation {
+ inherit name;
+
+ src = fetchurl {
+ url = "https://dl.suckless.org/dwm/${name}.tar.gz";
+ sha256 = "03hirnj8saxnsfqiszwl2ds7p0avg20izv9vdqyambks00p2x44p";
+ };
+
+ buildInputs = with pkgs; [ xorg.libX11 xorg.libXinerama xorg.libXft ];
+
+ prePatch = ''sed -i "s@/usr/local@$out@" config.mk'';
+
+ postPatch = ''
+ cp ${./dwm/config.h} ./config.h
+ '';
+
+ patches = [ ./dwm/autostart.patch ];
+
+ buildPhase = " make ";
+
+ meta = {
+ homepage = "https://suckless.org/";
+ description = "Dynamic window manager for X";
+ license = stdenv.lib.licenses.mit;
+ maintainers = with stdenv.lib.maintainers; [ viric ];
+ platforms = with stdenv.lib.platforms; all;
+ };
+ };
+in {
+ environment.systemPackages = with pkgs; [ hack-font st dwm ];
+
+ networking.hostName = "its-a-me";
+}
+```
+
+Now let's create the mario user:
+
+```nix
+{
+ # ...
+ users.users.mario = { isNormalUser = true; };
+
+ system.activationScripts = {
+ base-dirs = {
+ text = ''
+ mkdir -p /nix/var/nix/profiles/per-user/mario
+ '';
+ deps = [ ];
+ };
+ };
+
+ services.xserver.windowManager.session = lib.singleton {
+ name = "dwm";
+ start = ''
+ ${dwm}/bin/dwm &
+ waitPID=$!
+ '';
+ };
+
+ services.xserver.enable = true;
+ services.xserver.displayManager.defaultSession = "none+dwm";
+ services.xserver.displayManager.lightdm.enable = true;
+ services.xserver.displayManager.lightdm.autoLogin.enable = true;
+ services.xserver.displayManager.lightdm.autoLogin.user = "mario";
+}
+```
+
+The autostart file is going to be located in `/home/mario/.dwm/autostart.sh`. We
+could try and place it manually on the filesystem with a NixOS module, or we
+could use [home-manager][hm] to do this for us. Let's have home-manager do this
+for us. First, install home-manager:
+
+[hm]: https://rycee.gitlab.io/home-manager/
+
+```console
+$ nix-channel --add https://github.com/rycee/home-manager/archive/release-20.03.tar.gz home-manager
+$ nix-channel --update
+```
+
+Then let's add home-manager to this config:
+
+```nix
+{
+ # ...
+
+ imports = [ ];
+
+ home-manager.users.mario = { config, pkgs, ... }: {
+ home.file = {
+ ".dwm/autostart.sh" = {
+ executable = true;
+ text = ''
+ #!/bin/sh
+ export LIBGL_ALWAYS_SOFTWARE=1 # will be relevant later
+ '';
+ };
+ };
+ };
+}
+```
+
+Now, for the creme de la creme of this project, let's build Super Mario 64. You
+will need to get the base rom into your system's Nix store somehow. A half
+decent way to do this is with [quickserv][quickserv]:
+
+```console
+$ nix-env -if https://tulpa.dev/Xe/quickserv/archive/master.tar.gz
+$ cd /path/to/folder/with/baserom.us.z64
+$ quickserv -dir . -port 9001 &
+$ nix-prefetch-url http://127.0.0.1:9001/baserom.us.z64
+```
+
+This will pre-populate your Nix store with the rom and should return the
+following hash:
+
+```
+148xna5lq2s93zm0mi2pmb98qb5n9ad6sv9dky63y4y68drhgkhp
+```
+
+If this hash is wrong, then you need to find the correct rom. I cannot help you
+with this.
+
+Now, let's create a simple derivation for the Super Mario 64 PC port. I have a
+tweaked version that is optimized for NixOS, which we will use for this. Add the
+following between the `dwm` package define and the `in` statement:
+
+```nix
+# ...
+ sm64pc = with pkgs;
+ let
+ baserom = fetchurl {
+ url = "http://127.0.0.1:9001/baserom.us.z64";
+ sha256 = "148xna5lq2s93zm0mi2pmb98qb5n9ad6sv9dky63y4y68drhgkhp";
+ };
+ in stdenv.mkDerivation rec {
+ pname = "sm64pc";
+ version = "latest";
+
+ buildInputs = [
+ gnumake
+ python3
+ audiofile
+ pkg-config
+ SDL2
+ libusb1
+ glfw3
+ libgcc
+ xorg.libX11
+ xorg.libXrandr
+ libpulseaudio
+ alsaLib
+ glfw
+ libGL
+ unixtools.hexdump
+ ];
+
+ src = fetchgit {
+ url = "https://tulpa.dev/saved/sm64pc";
+ rev = "c69c75bf9beed9c7f7c8e9612e5e351855065120";
+ sha256 = "148pk9iqpcgzwnxlcciqz0ngy6vsvxiv5lp17qg0bs7ph8ly3k4l";
+ };
+
+ buildPhase = ''
+ chmod +x ./extract_assets.py
+ cp ${baserom} ./baserom.us.z64
+ make
+ '';
+
+ installPhase = ''
+ mkdir -p $out/bin
+ cp ./build/us_pc/sm64.us.f3dex2e $out/bin/sm64pc
+ '';
+
+ meta = with stdenv.lib; {
+ description = "Super Mario 64 PC port, requires rom :)";
+ };
+ };
+# ...
+```
+
+And then add `sm64pc` to the system packages:
+
+```nix
+{
+ # ...
+ environment.systemPackages = with pkgs; [ st hack-font dwm sm64pc ];
+ # ...
+}
+```
+
+As well as to the autostart script from before:
+
+```nix
+{
+ # ...
+ home-manager.users.mario = { config, pkgs, ... }: {
+ home.file = {
+ ".dwm/autostart.sh" = {
+ executable = true;
+ text = ''
+ #!/bin/sh
+ export LIBGL_ALWAYS_SOFTWARE=1
+ ${sm64pc}/bin/sm64pc
+ '';
+ };
+ };
+ };
+
+}
+```
+
+Finally let's enable some hardware support so it's easier to play this bootable
+game:
+
+```nix
+{
+ # ...
+
+ hardware.pulseaudio.enable = true;
+ virtualisation.virtualbox.guest.enable = true;
+ virtualisation.vmware.guest.enable = true;
+}
+```
+
+Altogether you should have a `configuration.nix` that looks like
+[this][confignix].
+
+[confignix]: https://gist.github.com/Xe/935920193cfac70c718b657a088f3417#file-configuration-nix
+
+So let's build the ISO!
+
+```console
+$ nixos-generate -f iso -c configuration.nix
+```
+
+Much output later, you will end up with a path that will look something like
+this:
+
+```
+/nix/store/fzk3psrd3m6x437m6xh9pc7bnv2v44ax-nixos.iso/iso/nixos.iso
+```
+
+This is your bootable image of Super Mario 64. Copy it to a good temporary
+folder (like your downloads folder):
+
+```console
+cp /nix/store/fzk3psrd3m6x437m6xh9pc7bnv2v44ax-nixos.iso/iso/nixos.iso ~/Downloads/mario64.iso
+```
+
+Now you are free to do whatever you want with this, including [booting it in a
+virtual machine][bootinvmmp4].
+
+[bootinvmmp4]: /static/blog/boot2mario.mp4
+
+This is why I use NixOS. It enables me to do absolutely crazy things like
+creating a bootable ISO of Super Mario 64 without having to understand how to
+create ISO files by hand or how bootloaders on Linux work in ISO files.
+
+It Just Works.
diff --git a/static/blog/boot2mario.mp4 b/static/blog/boot2mario.mp4
new file mode 100644
index 0000000..259902a
Binary files /dev/null and b/static/blog/boot2mario.mp4 differ
diff --git a/static/blog/portingmachinegobrrr.png b/static/blog/portingmachinegobrrr.png
new file mode 100644
index 0000000..874f11a
Binary files /dev/null and b/static/blog/portingmachinegobrrr.png differ