Skip navigation
NintendoAge
Welcome, Guest! Please Login or Join
Loading...

Advanced Nerdy Nights #4 Sprite 0 hit for a status bar

Aug 4, 2010 at 2:06:34 AM
bunnyboy (81)
avatar
(Funktastic B) < Master Higgins >
Posts: 7704 - Joined: 02/28/2007
California
Profile
This Week: After scrolling this tutorial should be pretty simple. Sprite 0 has a special PPU flag associated with it. Here it will be used to do split screen scrolling to enable a static status bar on the top of the screen.



Sprite 0 Hit Flag
Sprite 0 has a special flag in the PPU status register at bit 6. When a non transparent pixel of sprite 0 overlaps a non transparent pixel of the background, the flag is set. In the SMB example, sprite 0 is placed at the bottom of the coin icon. That is one part of the status bar that does not move.

 

In our example we first set the scroll registers to 0 for the static status bar. The nametable is also set to 0. That makes sure that the background and sprite 0 will overlap in the correct place.


NMI:

; all graphics updating code goes here

LDA #$00 STA $2006 ; clean up PPU address registers STA $2006 LDA #$00 ; start with no scroll for status bar STA $2005 STA $2005 LDA #%10010000 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1 STA $2000 ; start with nametable = 0 for status bar

LDA #%00011110 ; enable sprites, enable background, no clipping on left side STA $2001
Next we make sure the sprite 0 hit flag is clear, to avoid it being tripped from the previous frame. The flag is cleared at the end of vblank, so once it equals 0 you know the next frame has started.


WaitNotSprite0:
  lda $2002
  and #%01000000
  bne WaitNotSprite0   ; wait until sprite 0 not hit

Now we wait until the sprite 0 is hit. How long this takes depends on how far down the screen your sprite 0 is placed.


WaitSprite0:
  lda $2002
  and #%01000000
  beq WaitSprite0      ; wait until sprite 0 is hit

When that loop finishes, the PPU is drawing the first pixels of sprite 0 that overlap pixels on the background. We add a small wait loop so the rest of the status bar is drawn, and then change the scroll registers. The rest of the screen down is drawn using those settings.


  ldx #$10
WaitScanline:
  dex
  bne WaitScanline
  
  LDA scroll
  STA $2005        ; write the horizontal scroll count register
  LDA #$00         ; no vertical scrolling
  STA $2005
    
  LDA #%10010000   ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  ORA nametable    ; select correct nametable for bit 0
  STA $2000

So the order is:
  1 - set scroll to 0 for status bar
  2 - wait for sprite 0 hit = 0
  3 - wait for sprite 0 hit = 1
  4 - delay so scanline finishes drawing
  5 - set scroll for level background

The only other change is to make sure your graphics updating code does not draw over the status bar. The previous DrawNewColumn function handles the graphics updates so it has a few small differences. The starting address is increased by $80 to skip the first 4 rows of background. Then the source address is increased by $04 for the same reason.



Putting It All Together
Download and unzip the sprite0.zip sample files. sprite0.asm is the same as the previous scrolling5.asm file plus the changes covered here. This is another good one to watch in an emulator.


Edited: 08/04/2010 at 10:32 AM by bunnyboy

Aug 4, 2010 at 2:13:05 AM
RetroBasement (142)
avatar
(I read PM's !) < King Solomon >
Posts: 4977 - Joined: 02/15/2010
Ohio
Profile
wow dude thats awesome you put these together if i knew what any of this meant id totally be into it. im sure your helping alot of ppl on here

-------------------------
 

Aug 4, 2010 at 6:54:00 AM
CMR (4)
avatar
< El Ripper >
Posts: 1438 - Joined: 04/26/2008
United States
Profile
I can't wait till I get some time on my hands to go through all these.

Aug 4, 2010 at 12:18:57 PM
NESHomebrew (21)
avatar
(Brad Bateman - Strange Brew Games) < King Solomon >
Posts: 4264 - Joined: 04/28/2008
Saskatchewan
Profile
Very helpful! Thanks Brian. I was thinking about putting something together for the NESDev coding competition, and these last two NNs really helped me understand these concepts.

Oct 15, 2013 at 5:37:50 AM
y(oYo) (0)

< Cherub >
Posts: 11 - Joined: 06/25/2013
France
Profile
At this point, waiting for sprite 0 to be hit confuses me.

When we get out of the loop that tests if sprite 0 have been hit, we are outside the vblank period, right ?

WaitSprite0:
  lda $2002
  and #%01000000
  beq WaitSprite0      ; wait until sprite 0 is hit

So, it is actually possible to do graphics update in real time, even if the ppu is rendering?
Or maybe, at this exact moment, all we can do is only update Scroll registers?

Any help or futher information would be very appreciated
Thanks a lot.

-------------------------
NintAndBox.net[email protected]
The free DIY Nintendo repro boxes library - In english since early 2013, previously known as NpES


Edited: 10/15/2013 at 07:25 AM by y(oYo)

Oct 15, 2013 at 8:55:56 AM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
All you are doing is waiting for the hit, and on the hits, you can update either scrolling or the graphics bank. The PPU just reads the ROM, we can switch the ROM data at our will at ANY point.

Oct 15, 2013 at 9:34:21 AM
y(oYo) (0)

< Cherub >
Posts: 11 - Joined: 06/25/2013
France
Profile
Allright, and can we also update parts in our nametables here?
Or is it a bad practice?

What I am trying to do is to evaluate the ability to put the sprite 0 in the middle of the screen, and then manage the top and the bottom part to scroll independantly.
I don't know if it is possible.

Thanks.



-------------------------
NintAndBox.net[email protected]
The free DIY Nintendo repro boxes library - In english since early 2013, previously known as NpES

Oct 15, 2013 at 10:58:29 AM
Shiru (0)

(Shiru Shiru) < Meka Chicken >
Posts: 677 - Joined: 06/08/2011
Russian Federation
Profile
VRAM access is not possible during active rendering, so no nametable or palette updates. Changing rendering parameters is possible, like switching to another CHR bank or changing scroll value.

Independent scroll of top and bottom parts of the screen is possible. But it is not really related to the Sprite 0 hit, as it is only one of methods of catching specific scanline. The same could be done with well timed code, or with a mapper with scanline IRQ.


Edited: 10/15/2013 at 11:00 AM by Shiru

Oct 15, 2013 at 12:24:24 PM
y(oYo) (0)

< Cherub >
Posts: 11 - Joined: 06/25/2013
France
Profile
Right, thanks a lot for the hints.
So I guess I have to improve my dev skills in order to implement such stuffs ^_^

-------------------------
NintAndBox.net[email protected]
The free DIY Nintendo repro boxes library - In english since early 2013, previously known as NpES