sonder wrote:
ulfalizer wrote:
As no one seemed to mention it: Battletoads does keep rendering disabled for 20 or so (iirc) scanlines into the frame, showing that some commercial games did it at least (maybe lots of games did, but I only know of that one). This is what makes it tricky to emulate, as the current screen position needs to be within a certain interval when rendering is turned on for a sprite zero hit to happen. If that sprite zero hit does not happen, the game freezes.
As others have said, you'd need to set up the scroll yourself via $2006 writes before you turn on rendering if you keep rendering disabled on the pre-render line. The reason is that the "vert(v) = vert(t)" (copy vertical scrolling bits from t to v) operation in
http://wiki.nesdev.com/w/images/4/4f/Ppu.svg does not happen with rendering disabled. If you turn off rendering near the end of the frame instead and turn it on before the pre-render line, you would not need to use $2006 writes.
Thanks for adding your explanation ... though despite that I admit I'm still a bit lost.
How does the sprite 0 hit factor into this? It would have to be used strictly to disable rendering at the bottom of the frame, right? So no splitscreen without scanline hardware of some kind, or tricky-as-hell cycle counting, right?
Yeah, if you determine when to disable rendering through a sprite zero hit, it would make most sense if it was for extra VBlank time at the bottom of the frame.
For Battletoads, the sprite zero hit comes after rendering is re-enabled (as it would have to, as no sprite zero hits can happen with rendering disabled) and so is really unrelated to the extra VBlank time. It just happens that messing up the timing related to the extra VBlank time also messes up the sprite zero hit.
sonder wrote:
How does Battletoads know when to re-enable rendering at the right scanline? Scanline hardware?
Through tricky-as-hell cycle counting.
sonder wrote:
Everyone keeps mentioning $2006 writes for setting up the scroll. How does that work? But it only matters if rendering hasn't been enabled by the "first" scanline (the pre-render scanline as you referred to it). If it's not a big deal to do the scroll through $2006 then that's not a detractor.
http://wiki.nesdev.com/w/index.php/The_ ... _scrolling goes over it. Basically, the VRAM address register (often called
loopy_v or just
v, used for the address during $2007 reads/writes) gets reused during rendering to hold the current nametable position (if you check the red cells in the linked diagram, you can see it getting updated during rendering to move between tiles). On the pre-render line (which is the line before the first visible line), the starting position (which is held in
loopy_t/
t) is copied over to v, but only if rendering is enabled. If rendering is disabled,
v never gets initialized to the starting position, and you have to do it yourself via $2006 writes before you turn on rendering.
sonder wrote:
I still don't have a clear idea of what it will take to accomplish this in say, an NROM game. People say cycle counting but it seems to me like I could easily disable rendering at line 200 on sprite 0 hit and just make sure to re-enable it after my vblank routine. Anyone please confirm if my thinking's right on this or not though.
I think that should work, unless there's complications related to OAM (which is very glitchy). If it does, it would be easier than adding extra VBlank at the top of the frame I think. You'd just have to make sure to re-enable rendering before the pre-render line.