Catching Up
Hey, it’s been a while. A whole year has passed since the last update to this blog, and a lot has happened since then. It’s hard to explain why I haven’t written anything in so long, but I’ll give it a shot. My brain has a tendency to overthink things, and sometimes I get completely stuck because of it. When I was writing that post last year, I had originally planned to publish it on January 1st. I think I even had a rough draft finished before then, but no matter how many times I read over it and made changes, I was never happy with it. Working on it began to feel like a chore, and it got to the point where I was considering scrapping it entirely. Eventually I did manage to get it done, and it was posted two weeks later than it was supposed to. I’m glad I finished it, but I haven’t really felt like writing anything since.
I’ve been having similar feelings towards my programming projects lately as well. I kept trying things and getting stuck, having ideas that didn’t work, and eventually I lost motivation to work on anything. I didn’t want my projects to die though, so I forced myself to keep doing it. Of course, this achieved nothing aside from making me feel even worse. I’m trying to find ways to improve on this, and one of those ways is to stop overthinking everything so much. So, that’s what I’m going to do. I’m going to write this post without stressing over every little detail. There’s a lot to talk about, and not all of it is NooDS-related; I started a few side projects this year, and some of them should probably get their own write-ups eventually. For now though, I’ll just stick to the classics and go over what’s new with NooDS.
Performance has improved significantly thanks to a variety of optimizations, not the least of which being a proper scheduler. All events used to be hardcoded, and things like timers had to be updated on every cycle to ensure they triggered at the right time. With a scheduler, the only thing that needs to be updated is the time until the next closest event. That alone gives a sizable boost, but other optimizations such as software fastmem helped greatly as well. Instead of going through a bunch of conditions and logic every time something accesses the memory map, a giant lookup table is generated and the memory at any address can be found almost instantly. There are some special cases that fall back to the old method, but the majority of memory accesses are sped up significantly. There have been plenty of smaller optimizations as well, but it would take too long to detail them all. To sum it up, let’s compare a build of NooDS from a year ago to a build from today. The old build nets me around 290 FPS on the DS menu’s health and safety screen. On the current build, I get 720 FPS.
There have also been some accuracy improvements over the past year. Timing is tricky on the DS, mainly because of its memory cache, but I did add basic CPU instruction timings. These are essentially best-case timings; they assume that memory accesses always take one cycle, like they would on a cache hit. I’d like to attempt some form of memory timing eventually, but for now this is better than nothing! Another important addition was proper CPU pipelining. This doesn’t mean much for most games, but the Classic NES games on GBA abuse the pipeline as a weird anti-piracy check. These games are pretty crazy; if you’re interested in more details on what they do, I recommend this mGBA article. On the topic of GBA, it was brought to my attention that The Legend of Zelda: The Minish Cap was crashing before it got in-game. Turns out it relies on open bus shenanigans; essentially, it was reading from invalid memory which results in all sorts of weird behavior on hardware. There’s still work to be done here, but I did implement some basic open bus behavior which allows Minish Cap to work properly. These are only a few of the accuracy fixes that came in 2021, but there’s still a lot to cover, so let’s move on.
When it comes to features, NooDS is still a bit barebones. However, I did add a few things that make life a tad easier. There’s finally basic save type detection, and it works surprisingly well for most games. The manual override still exists in case you need it, but saving should generally be a painless experience now. I want to make the emulator more accessible, and another step towards that is firmware generation. If the user doesn’t provide a firmware file, NooDS will automatically build a basic one that’s good enough for directly booting games. BIOS files are still required, but without the need for a firmware, open-source alternatives like the DraStic BIOS can be used. This essentially eliminates the requirement for a user to dump anything except their games. Or, if you’re looking to run homebrew, you might be interested in the addition of DLDI support. Provided an SD image, homebrew can now perform file I/O just like on a flashcart! Lastly, although it’s more of an enhancement than a feature, I did some work on improving the emulator’s frame pacing. Especially on my 120Hz monitor, old versions were pretty choppy. Now, it’s nice and smooth on any refresh rate that’s a multiple of 60Hz.
Guess what? There’s still more. We welcome a new platform to the NooDS family, as the PlayStation Vita got an official port! I picked up a Vita on impulse one day, and equally impulsely ported NooDS to it. It doesn’t run that great, but I figured I’d add it to the official builds anyway. Speaking of builds, these are now set up to automatically publish as a release on GitHub, which means you no longer need an account to download them. The macOS build got some awesome upgrades thanks to Nadia, and it now produces a proper app bundle that you can install to your system. The Switch build also got some love, and now features touch controls in docked mode using either gyroscope or a joystick.
I think I covered most of the important improvements that NooDS has seen since the last time I posted here. For the future, I’m interested in writing my own high-level BIOS implementation, and also experimenting with local multiplayer support. I had some success in getting Mario Kart DS to detect open multiplayer lobbies, so there’s definitely potential there. I mentioned before that I started some side projects as well; I won’t go into detail here, but I added them to the projects page of this site and I might write some blog posts about them in the future. I’m not going to commit to any regular updates here, but I’ll definitely write more if I feel like it. Honestly, I’ve still been catching myself overthinking things as I write this, but it only took 2 days to finish it this time, so I guess I’m making progress? Anyway, if you got this far, thanks as always for reading my silly things. Take care of yourself, everyone!