VRAM? Lots of fun!
First of all, a little status update. From the previous list, DMA timings are covered, they're properly emulated except for cart DMA. I have also been fixing several GXFIFO related bugs, which lets most games run fine. Some badly programmed games (SM64DS or Rayman RR2, using immediate DMA instead of proper GXFIFO DMA) still overflow the FIFO a little, and since I haven't yet figured out why, I added a little hack to cover that for now.

Improving the 3D renderer, the other big TODO item, mostly means implementing textures. And also that weird focus I developed on making the renderer pixel-perfect.

Pixel perfection can be postponed. Most games would still be playable fine without it.

Textures mean supporting texture memory, which is a special case of VRAM mapping. I first want to revamp VRAM emulation to better match the hardware. There are notes about VRAM mapping in the melonDS code, and they have been there since a while now, waiting for a proper implementation.

Thing is, VRAM mapping on the DS isn't linear like with most old consoles. You get 9 VRAM banks of different sizes (from 16K to 128K), each can be mapped to different addresses for different purposes. GBAtek documents the mapping modes for each, but it's missing details like how the banks are mirrored and what happens if two or more VRAM banks overlap (which does happen in some games). So, I wanted to test that.

I first assumed the mapping was 1:1, as most DS emulators out there handle it. Which would mean that if two banks overlapped, it would either map the last one, or apply a priority order. So the first test was to map banks A and B to different addresses, write 0x1111 into A and 0x2222 into B, then map them at the same address and read, then do it again but map in a different order. The results would tell whether A has priority over B, or B over A, or whether it just maps the last bank.

The result wasn't quite what I expected. The tests didn't read 0x1111 or 0x2222, they both read 0x3333.

VRAM mapping isn't a 1:1 table. It basically just tells each bank which address range it should respond to. When two banks share an address range, they respond at the same time: writes go to both banks, and reads read from both banks too, ORing the values together, as shown above.

VRAM mirroring is also funky, each bank is mirrored in its own way, and the mirroring scheme doesn't depend on the bank's size. But for special cases like extended palettes or texture memory, mirroring doesn't matter.

I have yet to finish covering the VRAM mapping oddities without completely killing performance, and make the 2D GPU code suck less. Once that's done, we can get to the fun part of implementing textures in the 3D renderer.
Lurkon says:
Feb 25th 2017
Please keep writing these, really awesome!
Niklink says:
Mar 8th 2017
Just wanted to say that I check back here every day. It'll be months and months but I'm excited at the possibilities here. Keep it up!
yezi says:
Mar 13th 2017
When is the new post?
Timbo says:
Mar 14th 2017
Just wanted to drop by and say that I'm really excited to see where this goes! Good luck with your progress!
Belldandu says:
Mar 14th 2017
Great work m8. I see lots of promise. In the future i may donate a bit of money if you ever add some way to do so.
Coda says:
Mar 30th 2017
I've tried my hand at Wii homebrew, but never DS. I'm curious: Given that they both call their graphics APIs "GX", how similar are their 3D graphics stacks?
StapleButter says:
Apr 27th 2017
I don't know about the SDK, but the DS GPU is completely different from that of the GC/Wii.
Post a comment