The DSi camera adventure
I mentioned the DSi cameras in my previous post, and that's what I was working on lately. Mostly trying to get the cameras going on the DSi itself, so I could test the transfer hardware.

Well, it's not been that easy.

I had started work in the dsi_camera branch, but so far it was a large trainwreck. I couldn't really understand how camera transfers work and how everything interacts together. My attempt at a guessed implementation was getting nowhere, which meant it was time for some hardware research.

So I started work on a DSi camera test homebrew. I first went and implemented the initialization procedure found in GBAtek, only to be rewarded with a hang when trying to activate a camera. I tried many things, taking the init procedure from some open-source Aptina MT9V113 driver (the model of camera the DSi uses), reverse-engineering the DSi camera app to use its exact init procedure, all to no avail.

I felt stuck there. I even tried looking for existing examples using the DSi cameras, found this one by Epicpkmn11, but at the time it seemed to have the same issue I was having.

I eventually went out and asked for help on several places. A side effect is that I'm now found in some Discord servers. I also posted a thread at nesdev, knowing nocash hangs around there. The documentation in GBAtek implied he did get the cameras working, so I figured he'd be able to help. And he did, thanks there.

I first looked at the code he provided, checking for any meaningful differences in the init procedure, but it looked like I had all the essential stuff right. I was stumped.

It eventually occured to me that maybe I should try initializing both cameras simultaneously, like Nintendo does, rather than only initializing one camera. You know how it is, when you're desperate, anything can look like a valid solution. Anyway, that didn't cut it, but it revealed something interesting when I tried to read some registers from both cameras. Some reads were getting corrupted. So I knew something was up with the I2C code.

Looking at nocash's I2C code, I was able to spot and fix the issue. Turns out that during an I2C read, you don't raise an ack when reading the last byte. This fixed the corruption I was observing, and finally allowed the camera to activate successfully. At the same time, Epicpkmn11 happened to be in the same Discord server I was in, so they could fix their code too (turns out it did have the same issue as mine).

Next thing I did was enable a camera transfer, and, lo and behold, I was able to display camera input on my DSi. From this, I tested the camera transfer hardware in several ways, to try figuring out how it works.

Details are still hazy, but this time I was able to make a working implementation in melonDS.

I made the data register return a fixed value, hence the red/blue stripes. But now that we have a working base, next step is feeding an image buffer into this, and ironing out the remaining issues (for example, taking a picture causes a system error).

But after that, I felt like chilling some, and figured I would try finding out why ZXDS was running abysmally slow in melonDS. Basically, ZXDS is a ZX Spectrum emulator for the DS. I'm not into Spectrum emulation, but from what I could read, the emulator is quite impressive technically, and I enjoyed reading the author's developer diary.

Anyway, ZXDS abuses the DS's writable VCount to limit the framerate to 50FPS. To quote its author:

Having this common master frequency, it was now simple to use it for converting T cycles passed to amount of samples to generate, as well as to use it to set up a timer which would count the 50Hz which would drive the LCD, and still keep everything in perfect sync. The refresh rate of the LCD itself can't be set directly, though, however the DS features a writable VCOUNT register which can be used to delay the start of the next frame as needed. It is normally intended to be used to synchronize display of machines participating in multiplayer games, but it was trivial to abuse it for holding the retrace after each frame displayed until the interrupt handler driven by the 50Hz timer allowed it to go, effectively slowing the LCD refresh rate to 50Hz as well.

Technically, ZXDS uses two cascading timers to achieve this. Timer 2 is set to an interval of 16 cycles, and drives timer 3 which is set so that its IRQ will fire every 20ms. ZXDS will then hold VCount at a certain value until the IRQ fires. All fine and dandy.

Of course, as far as melonDS is concerned, this is where the problem was lying. ZXDS would hold VCount for way too long, causing each frame to last absurdly long. Sure enough, the issue came from the timers. What, a timer issue in melonDS in 2020? Madness!

In particular, it came from timer 2 and its tight interval. melonDS updates its timers more loosely than the actual DS, but it assumed a timer would only overflow once after each update. What happened here was that updates were far enough apart that timer 2 had the time to overflow more than once. The assumption that it would only overflow once caused it to start behaving wrong, and that is why the timer 3 IRQs were so far apart.

So I did something similar to audio timers, which are updated every 1024 cycles (and do take into account the fact that they could overflow several times in one update). This fixed the issue, ZXDS now runs at the expected 50FPS.

Nov 2nd 2020
jan says:
Nov 2nd 2020
Are you being INTENTIONALLY dense?!
Arisotura says:
Nov 2nd 2020
calm the fuck down, you two.

direct mode uses pcap, works best but only on Ethernet connections. indirect mode has no restrictions but might break.
jan says:
Nov 2nd 2020
Thanks for clearing that up. Sorry for my anger.
AsPika2219 says:
Nov 2nd 2020
Waitng for proper DSi Camera function! ๐Ÿ˜Ž๐Ÿ‘ Plus... Arisotura ๐ŸคMartin "NoCash" Korth
thatGuysN64 says:
Nov 6th 2020
very impressive :P so im just guessing that webcams will be possible to use at one point with melonds?
Nov 7th 2020
Nov 9th 2020
Generic aka RSDuck says:
Nov 10th 2020
while I agree that those posts are annoying (maybe we should adopt a similar policy on Pokemon games as desmume ;)) please don't use autistic as an insult.
jan says:
Nov 11th 2020
there seems to be a strong correlation between pokemon games and the people playing them being insufferable little children. be that as it may, a lack of agnosticism towards the things people emulate is exactly what caused so much drama and heartache with desmume
Anon says:
Nov 11th 2020
Oh God, Please don't have the same policy as those DesMuMe devs. I beg you. this is such a great forum and emu. Don't denigrate everything just because of one douche.
Anon says:
Nov 11th 2020
Would you guys be willing to add MacOS support anytime soon? Asking for a friend.
Arisotura says:
Nov 11th 2020
nah, the bit about the DeSmuME policy was mostly a silly joke

also, yeah, MacOS support is being worked on
Anon says:
Dec 5th 2020
Oh my god you guys actually did the macOS thing thank you thank you sooo much!
Rayyan says:
Dec 5th 2020
Has your friend tested it yet Anon?
Post a comment