It is currently Tue Apr 22, 2014 11:46 pm

All times are UTC - 7 hours




Post new topic Reply to topic  [ 81 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
 Post subject:
PostPosted: Thu Dec 25, 2008 1:37 pm 
Offline

Joined: Wed Mar 22, 2006 8:00 am
Posts: 354
Some clarification:

1. If sprite 0 is the only sprite in range, then OAM $20-27 is corrupted. Suppose sprite 1 is the only one in range. Which sprite pair is corrupted? If I'm reading right, you're saying that the same pair is corrupted (OAM $20-27). Or, are you saying sprite 1 causes the same pair to be corrupted, but it's a different pair from sprite 0 (e.g. $40-47 instead)?

2. Suppose both sprites 0 and 1 are in range. What sprite pair gets corrupted in this case? I want to know if the corrupted sprites (1) depends on the total number of sprites found, (2) depends on the first (or last) sprite found, or (3) is always $20-27 (provided shut-off is in the OAM scanning period mid-scanline).

3. If none of the first six sprites are in range, there is no corruption? Are you sure of this? Perhaps you were shutting off the PPU before the seventh sprite was evaluated? (I have an idea what might be causing the bug, but my idea will go out the window if only sprites 0-5 cause the problem.)

4. What happens if $2004 is read during the first 64 cycles of the pre-render scanline?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 29, 2008 9:03 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 11721
Location: NE Indiana, USA (NTSC)
Tetramino 0.33: no more flicker, among numerous other changes.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 03, 2009 11:10 am 
Offline

Joined: Wed Mar 22, 2006 8:00 am
Posts: 354
I was hoping to get answers to my questions, but oh well. Here's my idea of what's happening.

My theory is that the corruption is being caused by the fact that there are two different sections of OAM. The primary OAM, which is 256 bytes, contains all 64 sprites and is ultimately what is written to during sprite DMA, etc. Secomdary OAM is 32 bytes and contains the 8 sprites that are in range for a particular scanline. At the start of a scanline (cycles 0-63), the sprite engine sets all bytes in secondary OAM to $FF (reading $2004 returns $FF during this period). During cycles 64-255, primary OAM is scanned and any sprites that are in range are copied to secondary OAM. During H-Blank (cycles 256-319), secondary OAM is scanned, and each in-range sprite is processed for display on the next scanline (CHR data is fetched, etc.). The sprite engine is inactive from cycles 320-340.

At the end of each scanline, the secondary OAM address will always be zero, but during a scanline (including H-Blank) this address becomes non-zero. What I'm thinking is that if the secondary OAM address is non-zero at the time the PPU is turned off, then its address will determine which pair of sprites will be corupted at the start of the next frame. There are 32 bytes in secondary OAM, and there are also 32 sprite pairs in primary OAM, so my guess is that if you multiply the secondary OAM address by eight, you'll get the first byte in primary OAM that gets overwritten.

If this is the case, then turning off the PPU between cycles 64 and 255 on a line with no in-range sprites will not cause the glitch, since the secondary OAM address will stay at zero. If there are in-range sprites, then the address will become non-zero and cause the glitch to happen. During H-Blank, and during the first 64 cycles of each scanline, the secondary OAM address always changes whether there were sprites on that line or not. Theoretically, the address should be zero between cycles 320 and 340, but that's probably too small of a window to be used in most applications.

I would like to see this tested. I hope there's a way to predict the corruption so that emulators can implement it. Nestopia does have the recent controller read/DPCM bug implemented - maybe this is another one that could be added to that emu.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 21, 2010 10:15 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2077
Location: Minneapolis, Minnesota, United States
I understand this topic is pretty old, but I think I was having an issue related to this. The issue would -only- happen on hardware, as a result of a failed sprite #0 hit.

In my current project, I have a status bar at the top, with a sprite #0 hit happening at pixel 31, 204. After this, the scroll is appropriately set and whatnot. In my test level, I have a part where the player can enter a cave by pressing the up button. When that happens, the "level initialize" routine is called to load the next part of the level. Since there is so much updating, I actually have to disable rendering and the NMI. This disabling of rendering was originally happening mid-frame. After that, a ton of updates would occur, and I would clear out everything but sprite #0 in my RAM page dedicated to OAM. At the end of the routine, I would wait for the next Vblank, re-enable rendering and perform a DMA transfer as well as re-enabling the NMI. The code I performed was as follows:

Code:
   lda #$00
   sta $2000
   sta $2001
   sta Standard.$2001
   sta Standard.$2000

....
;Whole ton of PPU updates
....

   lda $2002                  
-
   lda $2002
   bpl -
   
   lda #$1E
   sta Standard.$2001
   sta $2001

   lda #>Game.ObjectDraw.OAMPage
   sta $4014
   
   bit $2002
   lda #$88
   sta Standard.$2000
   sta $2000
   rts


Interestingly enough after this routine, what sometimes happened, and what sometimes didn't, was that the screen would come up displaying my status bar, and the background below, but absolutely no game logic was being processed. I added in some native debugging features to view the contents of RAM while testing the game on the powerpak, and I noticed the stack was overflowing as a result of the game never exiting the NMI. From a little more testing, I narrowed it down to sprite #0; it was never detecting the hit.

What was strange is I was able to see the tile used for sprite #0 hits where it was supposed to be on the screen. Also, the page I used for DMA transfers appeared normal. The only thing was, since the game logic loop wasn't able to finish up its usual game logic in time for the first execution of the NMI, PPU updates were still locked, so it wasn't performing a DMA transfer within the NMI handler (It only performed the one at the end of the level init routine).

After hours of pulling my hair out, I noticed something that I think may be the cause of this problem. When I was disabling rendering, it was midframe, and the glitch would only happen when the player's sprite was on the scanline being rendered at the time of disabling! As I've said before, no emulator was able to recreate this behavior; it only happened on hardware. Looking at the contents of RAM, I saw absolutely nothing indicating there should not have been a sprite #0 hit when rendering was re-enabled.

So, with that aside, what I'm wondering is how I can effectively avoid this. The first thing I did once I discovered this was wait for the NMI to disable rendering. So I replaced:

Code:
   lda #$00
   sta $2000
   sta $2001
   sta Standard.$2001
   sta Standard.$2000


with

Code:
   lda #$00
   sta Standard.$2001                  ;Clear virtual PPU register
   lda Standard.VBLCount                        ;Wait for NMI; it will shut off the screen
-
   cmp Standard.VBLCount
   beq -
   
   sta $2000
   sta Standard.$2000


So that the NMI handler would see that I wrote #$00 to the virtual $2001 register, and then in turn write $00 to the real $2001 register (and of course, skipping the wait for sprite #0). After that NMI is executed (which would be seen by the difference of the originally loaded VBLCount and the updated VBLCount variable), the NMI would be shut off. So all together, this code would be disabling rendering during actual Vblank, and then shutting off the NMI. Would this be an adequate solution to the bug discussed in this thread?

Sorry if this is not enough information, or too much to make sense of. If clarification is needed, I would be happy to provide =).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 21, 2010 10:55 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 6495
Location: Rio de Janeiro - Brazil
Celius wrote:
Would this be an adequate solution to the bug discussed in this thread?

I think so. The whole problem is that disabling sprites while the sprite rendering logic is running causes it to act funny when they're enabled back. Since no sprites are rendered during VBlank, that seems to be a safe time to disable rendering.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2010 7:32 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3065
Some games disable sprites for 1 scanline, then turn off the screen at the next scanline. Is this always a safe way of doing things?

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2010 8:15 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 11721
Location: NE Indiana, USA (NTSC)
As I understand it, disabling sprites and leaving the background turned on only hides the sprites. It doesn't disable the sprite rendering pipeline.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2010 10:40 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 5916
Location: Jongny, VD, Switzerland
Yeah, and as I understand, the other way arround is true too : "disabling" background but not sprites only hides the BG, but the rendering pipeline still works as usual.

At least I was able to toggle the BG on/off without having any problems with scrolling (with sprites on) which soft of "proofs" this.

I guess the PPU only enters in it's "iddle" mode when both BG and sprites are hidden.
A total proof of it would be to use MMC3's scanline counter with BG or sprites (but not both) disabled and show that it works as supposed. Does any games/demoes do this ?

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2010 10:04 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2077
Location: Minneapolis, Minnesota, United States
Ha, I actually used this code as I wrote above:

Code:
   lda #$00
   sta Standard.$2001                  ;Clear virtual PPU register
   lda Standard.VBLCount                        ;Wait for NMI; it will shut off the screen
-
   cmp Standard.VBLCount
   beq -
   
   sta $2000
   sta Standard.$2000


And noticed that very strange things were going on visually. Sometimes, my status bar would be drawn as if PPU increment 32 was on, and there would also be very strange color glitches when the second half of the level was loaded. Hmmm.... Well, it could have something to do with:

Code:
   lda Standard.VBLCount                        ;Wait for NMI; it will shut off the screen
-
   cmp Standard.VBLCount
   beq -
   
   sta $2000
   sta Standard.$2000


Because if you look, the VBL count is actually getting stored in $2000! Woops. Adding an lda #$00 before that fixed that problem right away =).

And actually, relating to what you guys are talking about, I was curious about something. Is it not safe to do BG updates while BG rendering is disabled, but sprites are enabled?

_________________
-Owner of Poultry Games


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2010 10:10 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 6495
Location: Rio de Janeiro - Brazil
Celius wrote:
Is it not safe to do BG updates while BG rendering is disabled, but sprites are enabled?

No, it isn't. The PPU is only free for updates if both are disabled.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 23, 2010 7:15 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3065
Bregalad wrote:
A total proof of it would be to use MMC3's scanline counter with BG or sprites (but not both) disabled and show that it works as supposed. Does any games/demoes do this ?


Chu Chu Rocket does it, when it shows a dialog box, it disables sprites, but allows background, and the IRQ to end the box happens just like it should.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 23, 2010 11:36 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 6495
Location: Rio de Janeiro - Brazil
Dwedit wrote:
Chu Chu Rocket does it, when it shows a dialog box, it disables sprites, but allows background, and the IRQ to end the box happens just like it should.

Have you tested with an actual MMC3 chip? Because we all know that the PowerPak can't be trusted for these things.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 05, 2011 7:09 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 1701
Location: Tampere, Finland
Did any emulator ever implement this corruption behaviour?

_________________
Download STREEMERZ for NES from www.fauxgame.com!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 02, 2011 1:06 pm 
Offline

Joined: Mon Sep 27, 2004 2:57 pm
Posts: 730
I'm having a hard time following this thread, because there seems to be conflicting information.

Just so I have it straight, disabling sprite rendering on a scanline that has sprites on it will cause the sprite flicker glitch, unless you disable sprite rendering sometime between pixels 64-255 within the scanline?

Or do you have to avoid disabling between pixels 64-255?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 02, 2011 1:26 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 11721
Location: NE Indiana, USA (NTSC)
You have to avoid disabling while a sprite is in range, and you have to disable between x=64 and x=255. At least these rules worked for clearing up the flicker in LJ65 (formerly Tetramino).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 81 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group