Original Post

The VIP is somewhat simple, as long as you stick to BGs and OBJ primitives… I got arrogant, and now I realize I’m not as comfortable with the hardware as I’d like to think XD.

While reading about double-buffering to reacquaint myself with how modern 3d gfx are done, I realized that there are no restrictions on when a programmer can access character RAM or the frame buffers. This includes the times while the VIP is sending data to the LED arrays. Presumably, this is because character RAM and the framebuffers use dual-port RAM. Any new writes to a specific address will not be read properly until a minimum holding time has passed. Is this timing known?

In other words, does the VIP arbitrate access to dual-port RAM so new writes to characters of the frame buffer will not take effect until the next frame? Or is the amount of time it takes simply dependent on the RAM’s holding times? I could test later today of course if necessary :P.

I also noticed that in my demo as is right now, I access/rewrite BGMaps without actually needing to disable the display- vbDisplayOff() and vbFXFadeOut() only disable the LEDs (legal to change at any time, but becomes valid during the next column to be drawn). BGMaps do not seem to use dual-port RAM, so I was a bit surprised that I could write to it at any time without conflicts, even when the LEDs were off.

Curious about what would happen, I disabled the fades (which sync with when the VIP stops drawing) in my demo, and I can verify that there are no ill effects other than seeing a mix of old and new data for a few frames (< 1 second). Perhaps someone more knowledgeable than me re: the VIP can give me pointers about how to examine more edge cases, so I know how the timing of the VIP works in better detail? Nintendo's dev manual discuses the basic timings and includes how the pinouts of various components interact. However, I can't seem to find other timing details, such as how long after data is written to certain regions (besides certain VIP registers) will it become valid, and whether any regions (again, besides certain VIP registers) are locked during drawing? I'm used to the SNES world, where VRAM is locked outside of HBlank, VBlank, and Forced Blank, but I guess dual port RAM saves the day here. Still doesn't explain how BGMap access (which doesn't seem to be dual port) doesn't cause conflicts, however. I ask mainly because it seems that the amount of synchronization required to draw to framebuffers and BGMaps at will is nontrivial.

2 Replies

It’s my understanding that VIP memory is read/written by the VIP itself using the same or a similar I/O interface accessible by the CPU. As in, the VIP has to issue its own reads and writes, rather than change the values in its memory directly. I might be completely off here, but it lines up with what I’ve experienced (like the way my F-Zero project died when it came time to overlap some pixels).

I do know that window parameter memory has some scratch areas, such as those reserved regions of affine parameters. The VIP uses those areas to store working variables while it’s drawing. Again, it sounds to me as if the VIP is a sort of coprocessor that accesses video memory the same way the main IC does.

If that’s the case–and again, I could be totally wrong–then there will not be any restrictions regarding how or when VIP memory is accessed. After a write process completes, the data can be read. Is there a sort of mini bus in there that prevents the VIP and CPU from accessing the memory simultaneously? I have no idea how it works, but the mystical back of my brain where thoughts happen without my knowledge suggests that such conflicts are never an issue.

Here, have this salt shaker so you can take a few grains with what I just said. (-:

A bigger concern of mine is why do I care XD?

In actuality, I just want to understand the hardware’s timing so that I can write code that modifies framebuffers/registers with confidence that it will work on real hardware. I don’t want to get into the situation where I write something, expecting it to work 100%, and then I stumble upon an edge case, and struggle to figure out what went wrong.

At that stage, most likely I will have missed a minor edge case timing detail, and my code finishes JUST at the right time to screw up. Or worse: it’s a race condition that triggers seemingly at random :/.

 

Write a reply

You must be logged in to reply to this topic.