I'm making a vertical scrolling game on a basic (32K PRG 8K CHR) cartridge. I understand how nametables and basic scrolling works.
For now, my goal is to make a status bar at the top of the screen (32x3 tiles). I checked some Sprite 0 Hit threads but I don't quite understand how it works. Please, show a simple code for basic vertical scrolling splitting.
I also have more questions.
1. How to detect the current PPU scanline?
2. How to force load a scroll position?
Thanks in advance.
One scanline before a frame starts, $2002 bit 6 ($40 place value) becomes 0.
When an opaque pixel of sprite 0 and an opaque pixel of the background are drawn at the same position, $2002 bit 6 becomes 1. This event during the frame is called the "sprite 0 hit", as described in NESdev Wiki article "PPU OAM" section "Sprite zero hits".
What a program on the CPU does with it:
This is seen, for example, with the bottom of the coin in the status bar in the first Super Mario Bros.
Every vblank, the program sets the scroll position for the status bar, spins in a loop waiting for $2002 bit 6 to become 0 and then become 1, and then changes the scroll position for the playfield.
Now you have three smaller problems:
- How to line up sprite 0 with the bottom of the status bar to arrange for a sprite 0 hit to happen. The best way to arrange for this depends on a mock screenshot of what you want the top status bar and playfield to look like.
- How to wait for the sprite 0 hit. The simplest way that could possibly work is this:
Code: Select all
: bit $2002 bvs :- bit $2002 bvc :-
- How to change the scroll position mid-frame, which is trickier than setting scroll at the top of the screen especially if scrolling vertically. You'll probably need a sequence of writes to $2006, $2005, $2005, and $2006, as described in NESdev Wiki article "PPU scrolling" section "Split X/Y scroll". See tokumaru's code example in the topic "Screen split and vertical scrolling in the bottom half".
You can't. Not directly, anyway. Without a mapper, there are five options:
1- Wait for the sprite 0 hit flag to become true
2- Wait for the "9 sprites on a scanline" flag to become true
3- Count cycles
4- Magic with OAM evaluation
5- Magic with the DPCM IRQ
You could use a mapper with single screen mirroring, such as AxROM or MMC1. You would use mapper registers to swap nametables. The main screen on one nametable, the HUD on another nametable.
Example, Cobra Triangle.
I can't remember what it uses to time the split, but sprite zero hit would be the easiest.