Disabling rendering mid-frame

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Disabling rendering mid-frame

Post by pubby »

I'd like to disable rendering for the first 16 scanlines to do pattern table updates, but I'm concerned about OAM corruption and Battletoad's dot crawl pattern.

I have heard that the way to prevent the dot crawl problem is to enable rendering for the first scanline after vblank and disable it right after, but I have also heard that doing so causes OAM corruption which is a much bigger issue than dot crawl.

Now, I've heard it said that OAM corruption won't occur when rendering is disabled between dots 176 and 256, but is that true? Do I have to worry about the placement of sprites at all? In that thread, Bananmos and Tokumaru both made it seem as though OAM corruption was unavoidable, even with carefully timed writes.

My current code is as follows. I would appreciate if others would look it over.

Code: Select all

    ; Do OAM DMA.
    lda #.hibyte(CPU_OAM)
    sta OAMDMA

    ; Enable rendering
    lda #PPUMASK_BG_ON
    sta PPUMASK

    ; Wait for the end of vblank.
waitForSprite0Clear:
    bit PPUSTATUS
    bvs waitForSprite0Clear

    ; Draw the first scanline with rendering enabled, then turn rendering off. 
    lda #157
    jsr delay_A_plus_25_cycles
    lda #0
    sta PPUMASK ; This write happens after dot 176 but before dot 256

    ; Animation frames run in a fixed amount of cycles.
    bankswitch_to anim_frames_lo
    jsr jumpToAnimationPtr

    lda #88
    jsr delay_A_plus_25_cycles

    ; Turn rendering back on
    lda #PPUMASK_SPR_ON | PPUMASK_BG_ON
    sta PPUMASK ; This write happens after dot 256
Does this look like it will work?

I don't own an NES and so I have no way of testing this on real hardware.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Disabling rendering mid-frame

Post by thefox »

Unfortunately, I don't think the sprite corruption details have been nailed down, so testing on hardware feels mandatory.

One idea that came to mind, although I haven't tested this, would be to do OAM DMA in forced blanking, just before rendering is re-enabled. That way, it wouldn't matter if the earlier disabling of rendering corrupted them. I'm pretty sure there are one or two games which do OAM DMA midscreen, so at least the concept should work.

BTW, to folks familiar with Visual2C02: can it simulate the OAM corruption correctly?
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Disabling rendering mid-frame

Post by tokumaru »

thefox wrote:One idea that came to mind, although I haven't tested this, would be to do OAM DMA in forced blanking, just before rendering is re-enabled. That way, it wouldn't matter if the earlier disabling of rendering corrupted them.
The thing is, it's not disabling rendering that corrupts sprites, it's re-enabling that does it! (Relevant link) This quirk is nastier than most people make it out to be.

The moment at which you disable rendering is important because it defines what the PPU will do when rendering is re-enabled, which is when the corruption may actually take place, so doing the DMA during forced blanking doesn't solve anything.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Disabling rendering mid-frame

Post by thefox »

tokumaru wrote:The moment at which you disable rendering is important because it defines what the PPU will do when rendering is re-enabled, which is when the corruption may actually take place, so doing the DMA during forced blanking doesn't solve anything.
Ah, so when it's disabled the PPU is left in a certain state and then resumes in a glitched way when rendering is re-enabled?

Anyways, I'm pretty sure there are some games that do OAM DMA during forced blanking midscreen, so it must be doable with proper timing, but I can't remember the name(s) of the game(s).

EDIT: Skull & Crossbones (Tengen, unlicensed) was the game I was thinking of. It has two player split screen and does OAM DMA in the middle. It's hard to say if it suffers from sprite corruption though.
Last edited by thefox on Sat Jun 04, 2016 9:39 am, edited 1 time in total.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Disabling rendering mid-frame

Post by rainwarrior »

tokumaru wrote:
thefox wrote:One idea that came to mind, although I haven't tested this, would be to do OAM DMA in forced blanking, just before rendering is re-enabled. That way, it wouldn't matter if the earlier disabling of rendering corrupted them.
The thing is, it's not disabling rendering that corrupts sprites, it's re-enabling that does it! (Relevant link) This quirk is nastier than most people make it out to be.

The moment at which you disable rendering is important because it defines what the PPU will do when rendering is re-enabled, which is when the corruption may actually take place, so doing the DMA during forced blanking doesn't solve anything.
If rendering was disabled during vblank, it's not a problem, though. What thefox suggested should work, as it solves the problem that OAM decays if not refreshed (or rendered) for longer than roughly the vblank period. (I don't know what the "battletoads dot crawl" issue is, though, so if you were trying to solve that, I dunno.)

When that thread you linked came up I tried to make sure the Wiki had warnings about it in PPU $2001 documentation, and Sprite Errata. I think the rule was that if you're disabling rendering outside of vblank, you must do it after pixel 192, or there's a chance of corrupting sprites on the next frame.

...and yes, testing on hardware is mandatory. You're in dark territory. I'd suggest to "do what Battletoads does" but apparently you want to try something even crazier. ;)
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Disabling rendering mid-frame

Post by thefox »

rainwarrior wrote:I don't know what the "battletoads dot crawl" issue is, though, so if you were trying to solve that, I dunno.
It refers to the skipped tick at (0,0) from http://wiki.nesdev.com/w/index.php/File:Ntsc_timing.png. If rendering is kept disabled at that point, the tick is never skipped, thus producing a different dot crawl pattern than normally. In Battletoads the screen is visibly more "crawly" than in other games when the screen is not scrolling.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Disabling rendering mid-frame

Post by pubby »

Thanks for the replies.

Let's say I ignore the dot crawl issue and keep rendering turned off from vblank to the 10th scanline. OAM DMA would be done less than 20 scanlines before rendering is turned on.

There wouldn't be any OAM corruption in this case, correct?

I want to know so that I'll have a backup plan when I test on real hardware and all hell breaks loose :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Disabling rendering mid-frame

Post by tokumaru »

rainwarrior wrote:If rendering was disabled during vblank, it's not a problem, though.
The OP does want to disable rendering shortly after rendering starts though, to avoid the alternate dot crawl pattern.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Disabling rendering mid-frame

Post by rainwarrior »

pubby wrote:Let's say I ignore the dot crawl issue and keep rendering turned off from vblank to the 10th scanline. OAM DMA would be done less than 20 scanlines before rendering is turned on.

There wouldn't be any OAM corruption in this case, correct?
In my testing, I found the OAM only remains stable for just over 20 scanlines. The minimum thing it needed to be able to do was survive a vblank, and as it turns out that's all it can do. If you start DMA within 20 scanlines of turning rendering on I think you'll be okay. (Give it a good hardware test though.)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Disabling rendering mid-frame

Post by tokumaru »

Oops, missed the post about ignoring the alternate dot crawl pattern!
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Disabling rendering mid-frame

Post by pubby »

I haven't had any luck sourcing a cheap NES and so I haven't been able to test on real hardware.

So...

Would any NTSC person be willing to 5-minute-test a ROM or two for me? If so, PM me.
Post Reply