So for the last three weeks or so I’ve been trying to make my own Nintendo DS emulator from scratch. After being disappointed by early performance results with melonDS’ new hardware renderer on the Switch, and thinking about which system I would most like to emulate, I was inspired to attempt a DS emulator of my own. By sacrificing some accuracy and being crafty with my design, the goal I have in mind is to create something that’s imperfect but fast. Of course, writing an emulator is no easy task, but I got to work and started researching.

I discovered a neat little demo called TinyFB.nds. I won’t explain it in too much detail in this post, but you can read up on what it is and how it was made here. It’s pretty interesting. Basically, it’s a super small DS program that does the absolute bare minimum required to make the screen red. I thought this would be a perfect starting point. So I started designing my emulator, laying out a sort of skeleton for memory and whatnot. After setting up some essentials, I started looking into an interpreter. Luckily 32-bit ARM is somewhat familiar territory for me; I actually just finished a university class focused around it last semester. That, coupled with the fact that I was able to easily see what instructions were involved in making TinyFB tick, led me to implement the handful of instructions needed to make it run. Just running it was no fun, though. I wanted to SEE the red screen. Luckily the DS’ VRAM display is pretty straightforward, and that’s what TinyFB uses. All I had to do was read some RGB values and draw them. At this point I didn’t set anything up resembling sane emulator display code; there were no scanlines, no timing, it was simply drawing data. The entire emulator was basically a huge pile of hacks designed specifically to run TinyFB. But there it was, a beautiful red screen!

TinyFB

Considering the circumstances, it didn’t mean much. But it was visible results, and that was encouraging. It took less than a day to get here; shorter than the two days it took me to get visible results out of my NES emulator! I tricked myself into thinking this project wouldn’t be so hard after all. Of course, I was completely wrong. After I got TinyFB kind of working, I focused on adding more instructions to the CPU. After all, that’s the most important part! I also reworked my GPU code into something somewhat resembling, well, GPU code. To test some things, I modified TinyFB to test a couple of different instructions as well as the other screen. Things were looking decent.

TinyFB modified

After this though, not much happened visually. At this point I was able to tell if the software was turning on the display (the displays are white when turned on), but nothing outside of TinyFB was able to do even that. So I kept working, and slowly implementing things as my test ROM asked for them. I compiled a simple libnds homebrew for this, and all it did was set the display to VRAM mode. Essentially it just made one screen white and one screen black. It seems incredibly simple, but in reality libnds homebrews do all kinds of crazy things to prepare before actually executing the main portion of the program, even if some of these things aren’t necessarily needed for what my homebrew was trying to do. I said I’ve been working on this for about three weeks; well, the TinyFB stuff was the first couple of days, and then the rest of that time was all focused on trying to get this simple homebrew to work. After about a week of implementing instructions and stepping though instructions one at a time to find all the stupid little mistakes I made in the interpreter, libnds homebrews were able to turn on the display. A breakthrough! Well, this just meant I was getting to the point where it was more than just ARM CPU instructions I needed to implement to progress further. I was hopeful, but before I knew it I was back to the painful cycle of implementing and testing, with no visible results. During this time I implemented things like THUMB instructions and the different CPU modes, as well as always fixing those pesky little mistakes that kept popping up and causing problems. Eventually I decided to try loading the BIOS into memory. There was an instruction in my homebrew that was trying to call a BIOS function, and while it was a trivial one that I could have easily implemented without the BIOS, I figured stepping through the BIOS would be a good opportunity to test all the things I’d been working on. The program successfully entered the BIOS function, and then proceeded to explode. I managed to uncover two fairly substantial CPU bugs from the debugging process here, and after that I loaded up my ROM expecting the usual white screens, and…

One of the screens turned black. The intended behavior of the homebrew I made! There was still so much I hadn’t implemented that I had assumed I needed, so I thought surely this was some sort of mistake. The ARM7 was getting hung up trying to access an I/O register, and the GPU was trying to call unimplemented interrupts, as a couple of examples. Just for fun, I went and added some code to my homebrew to paint the screen red, like TinyFB does. To my surprise, it worked! I had gotten so used to no results over the past few weeks I could hardly believe it. I played around with making my homebrew draw some patterns and even made an animated gradient that was working just fine.

libnds gradient

Even though it doesn’t look much more impressive than the TinyFB screenshots, the fact that it’s a libnds homebrew means that other homebrews are probably close to working as well. Of course I still have so much to do, but being able to write my own test programs and run them will be incredibly useful and much more interesting than the tedious debugging I was doing before that mostly consisted of crappy print statements I littered throughout my code. Most importantly this says to me that there is hope for this project to go somewhere, and maybe I can do it after all.

Anyways, I wanted to share the progress I’ve made because I think it’s pretty exciting. I can’t promise that this project will end up being the speedy DS emulator that the Switch needs, or if it’ll even be able to boot commercial games, but whatever happens I’ll be posting updates here. And obviously since this is a Patreon you’re welcome to donate to support the project, if you wish. I don’t intend to bar non-donors from any updates, and the source code will always be available on my GitHub should you wish to compile and test it yourself. At the very least I like these blog-style posts that Patreon allows me to make! Maybe I’ll make these posts visible to donors only for a couple days, but I probably won’t do anything more than that. Maybe if you have any fun ideas for donor tiers ($1, $5, etc.) let me know.

Oh, and one last thing, the name NoiDS may or may not be temporary. I have at least one other idea in mind right now, and NoiDS was pretty much just a placeholder based on a slight alteration of my NES emulator’s name, NoiES. That’s all for now, I hope you’ll join me on this crazy journey :)