👾 The Dungeon of Ymir: A Daughter, Disassembler, and Her Dad's RPG
My father, Fred Nachbaur, died of cancer in September of 2004. He was 53 years old. I had just moved to Canada not long before, and our relationship, which had always been complicated, never got the resolution that I think both of us probably wanted. He was brilliant, generous, stubborn, private, and deeply creative. He was a musician, an electronics/radio engineer, a programmer, and by all accounts the kind of person to whom cats would climb into his lap on a first visit.
I didn’t know him nearly as well as I wish I had, and the side I saw of him was very different than the one that others saw.
So why am I writing about this now?
I’m getting older, and while I’m still several years away from the age he was when he passed, I’m close enough that the math starts to feel real. As a parent of my own child I find myself reflecting more on my parents and their lives, seeing more similarities than I would’ve cared to admit even a few years ago.
My dad was a software engineer, just as I am, and I find myself wondering about his life, his accomplishments, and what made him tick. There are things about him that I’ll never get answers to. But there’s one artifact of his that I can study, take apart, and try to understand from the inside out.
That artifact is a video game he created called Dungeon of Ymir.
What is Dungeon of Ymir?
40 years ago in 1986, my dad wrote and self-published a dungeon-crawling RPG for the Timex Sinclair 1500 (known as the ZX80-based platform outside North America). He sold it through his own company, Silicon Mountain Computers, out of British Columbia. The game was, by any reasonable measure, a masterpiece of constrained software design.

Here’s what makes it remarkable: the ZX81 shipped with 1KB of RAM. With a 16KB RAM expansion pack, my dad managed to build a full RPG with nine dungeon levels, multiple monster types, spells, items, an experience system, and a quest to retrieve the Sword of Kaslo. Using only a small BASIC bootstrap routine to kick things off, the entire rest of the game was hand-written in Z80 assembly.
But he didn’t stop there. He somehow hacked the hardware to double the computer’s vertical screen resolution, forced it to render graphics on a machine that was only designed for text, and used it to show animated sprites. He even shipped a second cassette with a level editor so players could build their own dungeons. I always knew the game was impressive, but I didn’t fully appreciate just how impressive until much later.
Someone reviewed it in 2021 and confirmed what I’d always half-known: the game was an adaptation of Sword of Fargoal (1982), reimagined for hardware that had no business running anything that ambitious. The reviewer noted the graphics were “almost mind-blowing” for the ZX81, and frankly, that’s an understatement.
In a nutshell, my dad crammed the equivalent of a full dungeon crawler into 16 kilobytes of hand-written machine code. For context, the previous paragraph alone is over 500 bytes.
A girl discovering retro computers
I played Dungeon of Ymir a few times when I was a young teen. I remember the black-and-white dungeon corridors, the monsters, the brutal difficulty. But I was more interested in figuring out how the computer worked than in playing the game itself.
In the summer of 1993 I was visiting my dad at his home in the small town of Ymir, just outside Nelson, British Columbia. It was an old mining town during the gold rush, but had dwindled to a single street that grass was slowly beginning to reclaim, and consisted of a small row of old houses and a pub (which doubled as the local post office).
I’d finished reading all the books I brought with me, and with nothing to do except wander along the abandoned railroad track, I pulled out my dad’s forgotten ZX81 from a dusty old box in his workshop and started to poke around with it. He showed me how to hook it up to the TV and cassette player, and after trying a few of the programs on the casettes he had, I took my knowledge of BASIC from my own PC and applied it to his much older machine.

I quickly exhausted the computer’s capabilities, and when I ran into trouble with its display system, I taught myself Z80 assembly in an attempt to draw a simple smiley face. I spent hours poking around in the guts of the thing, ultimately building a simple tic-tac-toe game, but I was never able to get it to fully do what I wanted. I tried replicating some of what my dad’s game did, even going so far as to load his game into memory and stepped through its memory buffer to see what I could understand. But I was a kid, the ZX81 was a finicky machine, and I never got very far.
What it did provide me was a bare-metal insight into how computers work at a low level. With no operating system, utilites, or random-access storage to rely on, I had to understand how the CPU, memory, and display hardware worked together to get anything to show on the screen. It was a self-taught crash course in low-level programming that I would never have gotten otherwise, and it sparked a lifelong fascination with how software interacts with hardware.
Prior to this my mainstay was my 8088-based PC clone, which was a much more forgiving machine to learn on. I had a full-sized mechanical keyboard, a 5ÂĽ" floppy drive, and even a 20MB internal hard drive to work with. The Timex Sinclair on the other hand was so much simpler with a rubbery membrane keyboard, and I had neither the patience nor the skill to really get into it at that age. But I never forgot about it, and I always felt like there was something special about the fact that my dad had managed to create something so complex on such a limited platform.
Nostalgia and reminiscing
I hadn’t really thought about any of this in years until a recent conversation with my friend Emily. We were discussing our mutual love of retro computers and video gaming. I mentioned my dad’s game, almost as an aside, and the moment the words came out of my mouth I realized I wasn’t done with this story.
If you’ve ever lost someone before you felt like you truly knew them, you understand the impulse to look for them in the things they left behind. My father left behind music compositions, electronics projects, a tribute page full of warm remembrances, and this strange, brilliant little video game that most people have never heard of.
So I had an idea, an unconventional and probably slightly unhinged one: What if I tried to rebuild Dungeon of Ymir on modern hardware? Not a port, not an emulation, but a proper recreation. Walk through the code my father wrote, understand every decision he made, and rewrite it from scratch. Software archaeology as a form of connection.
I can’t ask him about his life, his struggles, or any parallels I’m inferring from my own life. But perhaps I can find some level of appreciation for him in his code.
I can’t sit across from him and ask him why he chose to implement the display hack the way he did, but maybe I can reverse-engineer an answer. It’s not quite the same as asking something meaningful, to find answers to the questions I have about him and his life, but it’s better than nothing.
Getting started: Cracking open the binary
I started by tracking down the raw binary data for the game, the kind of file originally intended to be recorded onto audio cassette tape (yes, really…that’s how you distributed software in the 1980s). From there, I pulled together some open-source tools from GitHub: zx81-utils for converting the tape format to BASIC, and z80dasm for disassembling the Z80 machine code he liberally spread throughout the code.
I fired up a Docker container in which to safely compile those open-source tools, fed it the binary, and started processing the raw data. Out came pages and pages of assembly, the actual machine code instructions my dad wrote by hand, over forty years ago. There’s something surreal about reading someone’s machine code decades after they wrote it.
l40a6h:
di ;40a6 f3 .
ld a,007h ;40a7 3e 07 > .
ld b,a ;40a9 47 G
l40aah:
nop ;40aa 00 .
djnz l40aah ;40ab 10 fd . .
add a,0efh ;40ad c6 ef . .
l40afh:
inc a ;40af 3c <
jr nz,l40afh ;40b0 20 fd .
ld b,0c0h ;40b2 06 c0 . .
ld de,00020h ;40b4 11 20 00 . .
ld hl,02000h ;40b7 21 00 20 ! .
ld ix,l40c0h ;40ba dd 21 c0 40 . ! . @
jr l40c8h ;40be 18 08 . .
Every INC A, NOP, or other assembly instruction was hand-written, and revealed his thought process, workarounds, and creative problem-solving, preserved.
Software archaeology with an AI copilot
Here’s where it gets interesting. Rather than try to parse thousands of lines of Z80 disassembly purely by hand (I’m dedicated, not a masochist), I used Claude within VS Code to help me analyze the game’s structure. Think of it as having an extremely patient colleague who happens to have the entire Z80 instruction set memorized and doesn’t mind being asked “but what does this block do?” four hundred times in a row.
Together, we’ve been performing what I can only describe as software archaeology, tracing the game’s control flow, extracting its sprites and maps, and stepping through the rules and lookup-tables that control the game. The goal is to break the entire thing down into a proper game design document that summarizes the rules of the game which I can use as the starting point for a modern rewrite.
It’s early days, but already the picture forming is remarkable. And quite frankly, the man was a genius.
The man was a genius
I need to explain something about the Timex Sinclair ZX81 to put what I’ve been finding in perspective. This was not a graphical computer. It was a text-based computer which could display characters from a built-in set, and that was it. The video display was driven by a routine baked into the ROM, the read-only memory soldered to the motherboard. You weren’t supposed to be able to change it. That was the deal. You got your 24 lines of blocky text characters and you were happy to get it.
My dad looked at that limitation and felt that wasn’t good enough.
I’d always known he’d somehow hacked the display, but I didn’t understand how until I started tracing through the disassembled code. Embedded within the game is a hand-written stretch of assembly that tricks the computer to avoid its own video rendering logic to use a specialized one hand-written by himself, embedded within the game’s code. The ROM-based display routine, which the hardware relied on to put anything on screen, was replaced by his own custom driver that doubled the vertical resolution of the display. On a machine that Sinclair designed to show plain text, my father hacked to render actual graphics, at a higher speed. And not just static graphics either, the game included character animations and smoothly moving sprites through dungeon corridors. On a computer that was never meant to draw a single pixel. This custom video driver is a work of art, not just a brute-force hack. It’s a carefully-optimized piece of code that has to execute in lockstep with the CRT’s electron beam to produce stable graphics.
He pulled the same trick with the audio cassette I/O driver. The standard ROM routine for loading programs from tape expected data in a specific format, essentially BASIC programs. My dad overwrote that driver too, replacing it with his own routine that could load the game as raw binary data embedded within a REM comment statement directly into the 16KB extension memory. This meant he could use every single byte of that expansion RAM for game code and data, bypassing the overhead of the BASIC interpreter entirely. The routine is similarly elegant — it implements its own protocol to stream binary data into the right memory locations, sidestepping the standard loading mechanism completely.
And the level data structures? Compact beyond belief. All game content was procedurally generated and placed throughout the maps at the start of a game, so each run-through would be unique. Stairs between levels, monster placements, booby traps, everything was generated at runtime. To save space, he used the static data in the computer’s ROM yet again as lookup tables to seed information about wall and game rules, borrowing conveniently-structured preexisting character set information for a completely different purpose.
That level of efficiency is what made the level editor on the second cassette possible: he designed the data format to be mutated in memory from one tape, which could then be carefully side-stepped by the actual game when it was later loaded from a different one.
In 1986…
On a machine with 16KB of RAM and a membrane keyboard. The man built modding tools before “modding” was even a word.
And then I found the thing that made me put down my coffee and just stare at my screen for a solid minute.
The code that rewrites itself
While running the disassembler, z80dasm spit out a warning I wasn’t expecting: Self modifying code detected!
If you’re not a low-level programmer, let me explain why that caught my attention. Self-modifying code means the program rewrites its own instructions while it’s running.
Computer programs are just data, a long sequence of bytes that, when processed by the CPU, tells it which operations to perform. Normally computers go to great lengths to prevent this data from being changed, since it could crash the computer, overwrite something it’s not supposed to, or in the case of malware on modern computers, to perform some suspicious actions.
In this case, the CPU executes a sequence of instructions, and those instructions include commands to reach back and change other instructions that haven’t executed yet, or that will execute again on the next pass. It’s the software equivalent of rewriting your car’s engine while driving down the highway. It’s dangerous, it’s hard to debug, and it’s brilliant if you can pull it off.
My dad successfully used this trick in at least two places.
Micro-optimizing the render loop
The first is a renderer optimization at address 0x4169. Three bytes at 0x415D are overwritten at runtime to switch the character-plotting instruction between a “draw filled” and “draw empty” variant.
Why? To avoid a conditional branch in the inner render loop. On the Z80, a branch costs extra clock cycles…not many, but when you’re drawing every single tile on screen, those cycles add up fast. By rewriting the instruction itself instead of branching, he saved roughly two cycles per tile drawn.
In a tight render loop running on a 3.25 MHz processor that’s already busy pretending to be a graphics card, that’s the difference between smooth rendering and a flickering mess. He was micro-optimizing at a level that most professional game developers of the era wouldn’t have bothered with.
Hijacking the interrupt table
The second is even wilder. During startup, 38 bytes are copied from 0x4082 to 0xC082, which happens to be the NMI interrupt vector region. The Non-Maskable Interrupt (NMI) is the mechanism the ZX81 uses to trigger its display routine, and fires at a regular timed interval that coincides with the TV’s own refresh rate, and the CPU jumps to whatever code lives at the NMI vector to handle screen rendering.
Normally that address points to the ROM’s built-in display driver. My dad’s code patches the NMI handler directly, overwriting it with his own display routine so that every time the interrupt fires, his code runs instead of Sinclair’s. That’s how he bypassed the standard slow-mode display generation entirely. That’s what enables smooth rendering on a machine with no hardware sprites, no framebuffer, and no graphics capability.
He hijacked the interrupt table to improve performance, double the screen’s vertical resolution, and enable features the original hardware never supported.
Game sprites encoded inside the character set
There’s one more piece to the puzzle that ties the graphics together. The sprite table sitting at 0x6200 holds 8-byte monochrome patterns for each of the ZX81’s 64 characters, 512 bytes total of custom font data. Encoded inside the binary was a substitute character set which he used to replace the one built in to the computer’s ROM.
Where the ZX81 would normally render a collection of pixels to represent characters such as “A” or “B” on screen, his code instead draws dungeon walls, floor tiles, monsters, treasure chests, and player sprites. Every piece of tile art in the game lives in this table, mapped over the standard alphabet. The ZX81’s text rendering system thinks it’s drawing letters, but it’s actually drawing a dungeon.

Suffice to say, this wasn’t someone working within the constraints of the hardware. This was someone who understood the hardware so deeply that they could hijack its interrupt handlers, rewrite its instructions at runtime, and repurpose its text engine as a tile renderer, to make the machine do things its designers never intended.
Where do we go from here?
I’m going to keep writing about this project as it progresses. There’s a lot of ground to cover such as the game mechanics, the dungeon maps, the monster’s movement and attack patterns, and eventually the rebuild itself. I don’t know how long it’ll take, and I don’t know exactly what I’ll learn along the way. But I know that sifting through my father’s code, trying to understand the choices of someone I never fully understood in life, feels like exactly the right thing to be doing right now.
If you’ve ever tried to rewrite a 40-year-old video game to better understand a parent you lost too soon, I’d love to hear from you! I certainly don’t think this is a common experience!
Regardless, stick around and follow along anyway. This is going to be a weird and wonderful ride!