|Home | Downloads | Screenshots | RSS|
VRAM? Lots of fun!
Feb 24th 2017, by StapleButter
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.
|5 comments have been posted.|