A Hint of Wi-Fi and a Sprinkle of Graphics
Well, I’m not really sure how I can top last month’s GBA support, but I did manage to get some noteworthy things done this month! I still haven’t figured out how to write creative intros, so let’s just pretend I said something clever and get on with the improvements.
Something that’s been on the to-do list for a while is wireless communications. Even though the official Nintendo DS Wi-Fi servers have long been discontinued, plenty of games still offer local multiplayer support, and most things that use some form of wireless connectivity expect the hardware to be functioning. At the moment I’m not looking to emulate any sort of actual connection between systems, but it would be nice to at least have some basic functionality so that things don’t crash and burn. Previously, stuff like PictoChat and DS Download Play would freeze while trying unsuccessfully to initialize the wireless hardware. Games like Pokémon spit out an error screen if they can’t get things set up properly, which is especially annoying in the fourth generation games where it prevents you from selecting your save file! As I mentioned previously, I added a “hack” to stall the initialization long enough to get around this, but it’s far from ideal. So I set to work implementing some of the behavior that these initialization procedures expect.
Eventually, as you can see, I managed to get both PictoChat and DS Download Play to work! Well, by “work” I just mean that they don’t freeze. But hey, it’s a start! Unfortunately I wasn’t able to get the Pokémon error screen to go away just yet, but it gets much further into the initialization process and now gives you plenty of time to select your save file. The hack is still in place for the time being, but hopefully it won’t be needed for much longer.
Outside of the Wi-Fi shenanigans, I mainly worked on improving existing components. I finally got around to implementing the last few interpreter instructions, as well as fixing some issues with existing ones. NooDS now passes every test in ARMWrestler! I also focused a lot on graphical improvements, specifically to the 3D renderer. Here are a variety of screenshots taken with last month’s build of NooDS:
All of these screenshots exhibit some sort of graphical issue. Now, let’s look at the same set of screenshots from the latest build:
Things are looking much better! I’ll go through the improvements one by one. In the top-left we have Mario Kart: Super Circuit. Its mode 7 effect was completely broken, because I wasn’t emulating the internal background registers properly. Basically, I was calculating the background offset from scratch for every scanline, but on actual hardware there are registers that are incremented after every scanline to keep track of the offset. If the registers are incremented by the same value each line then there’s no problem, but the mode 7 effect works by using different values each line. Understandably, this caused the effect to break horribly on NooDS. That’s pretty much the only fix on the 2D side of things; the rest is all 3D-related.
Speed round! Next we have the star select screen in Super Mario 64 DS. Missing texture transformations were implemented to fix the shiny effect, and W normalization was improved to fix the eyes. portalDS shows a good example of blocky interpolation, which has plagued my renderer from the start. The DS interpolates colors with 9-bit precision, which I knew, but derpy me kept converting back to 6-bit values before interpolating across the scanline. Pokémon Platinum on the bottom left is pretty straightforward; it’s showing off the new fog implementation. Pokémon Black 2 has an example of what I thought was a pretty clever way of handling transparency rendering. Each polygon can be assigned an ID, and any transparent pixel will not be rendered on top of a pixel with the same ID. I learned about this from Arisotura’s GBATEK addendum, which has a lot of useful information that GBATEK either lacks or got wrong. Finally, Final Fantasy IV shows another issue that was fixed thanks to the addendum. GBATEK’s description of the stencil buffer (used for shadow polygons) turned out to be entirely wrong; shadow polygons should now work properly for all games.
There are more improvements than what I covered here, but for the sake of time I’ll leave it at that. I’d like to mention that during my efforts to improve the 3D renderer, I started to consider edge marking and anti-aliasing implementations. I implemented wireframe polygons, and since I can reuse that code to detect polygon edges, I thought I was pretty much ready to go. Well, it turned out to be a bit more complicated than that. I was messing around with some tests I whipped up on my actual DS when I noticed that the edges used for wireframe, edge marking, and anti-aliasing can be one pixel larger than the normal polygon, depending on the edge slope. Arisotura has a great write-up on this phenomenon, and I want to get it right before I go any further with the effects that use it. Another plan for the future is to finally get a proper scheduler going, so I can set up some actual timing and maybe even get a speed boost if I play my cards right. I only mention this because I’ve already started the prep work for it, so it’s more likely that I’ll actually work on it instead of getting sidetracked with other things. Anyways, that’s enough of my rambling for now. Thanks a ton for making it to the end; I enjoy writing these, and if anyone enjoys reading them, that’s even better :)