Coding a scrolltext

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
oRBIT2002
Posts: 634
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Coding a scrolltext

Post by oRBIT2002 » Tue Mar 03, 2020 1:39 pm

It was along time ago I tried coding something on the NES and I have never coded a splitscreen scroll but I wanted to give it a try. I'm trying to code a simple scrolltext which means I want to scroll just a tiny portion of the screen.
I guess I have to time it with a sprite 0-hit (this must be done during the frame with a tight loop?) and then I've got to make sure I write that value during hblank to avoid glitches?
And a few pixels down I want to stop the scrolling. So how do I do this the most efficient way? Code a delay-loop that consumes a suitable amount of cycles and then stores 0*2 in $2005?
During the process I've described above, it seems like an awful amount of wasted CPU-cycles but perhaps it's the way you have to do it?

lidnariq
Posts: 10276
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Coding a scrolltext

Post by lidnariq » Tue Mar 03, 2020 2:23 pm

There are two halves to your question:
1- How do you do something at a specific location on-screen?
2- How do you do the actual scrolling at that location?

#2 has an article on nesdevwiki:PPU scrolling

#1 depends on the specific mapper. You can use timed code, wait for a sprite 0 hit, deliberately use the sprite overflow flag, misuse the DMC IRQ, or use a mapper with an IRQ.

User avatar
tokumaru
Posts: 12003
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Coding a scrolltext

Post by tokumaru » Tue Mar 03, 2020 3:09 pm

Timed loops are only a waste when there are other things that the CPU could be doing instead, otherwise it's OK. Just keep in mind that PAL and NTSC scanlines take different amounts of cycles, so your code must be aware of the type of console it's running on if you want to support all regions.

Mid-screen scroll changes on the NES aren't hard. If you need to change only the horizontal scroll, you can use the same registers you normally use to set the scroll during vblank (i.e. $2000 and $2005). Changes to the coarse horizontal scroll are delayed until the next scanline, while changes to the fine scroll happen immediately, so you may change $2000 during the visible part of the scanline, but the $2005 write should happen during hblank. Do note that you don't have the whole hblank period to do scroll changes, because the first tiles for the next scanline are fetched at the end of the current scanline's hblank, so try to finish the changes as soon as possible.

Vertical scroll changes are trickier, because the normal scroll registers don't affect the vertical scroll mid-frame. To pull that off you need a combination of $2006/$2005 writes, and some bit shuffling. I don't think you'll need that for scrolling text though, unless you want to do some sort of wavy motion.

Don't forget that with 2 name tables side by side you only have room for 64 characters, so you might need to update the text on the fly as it scrolls if you're displaying long messages.

User avatar
oRBIT2002
Posts: 634
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Coding a scrolltext

Post by oRBIT2002 » Fri Mar 06, 2020 1:55 pm

I'm having issues with sprite 0 hit, the flag obviously isn't cleared when read so I'm getting hits on different scanlines all the time. Any secret technique here to master this? :)

lidnariq
Posts: 10276
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Coding a scrolltext

Post by lidnariq » Fri Mar 06, 2020 1:57 pm

You only get one split with the sprite 0 hit, and you only get one split with the sprite overflow flag. If you need more than these two, or if either's unsuitable, you have to use timed code or IRQs.
Last edited by lidnariq on Fri Mar 06, 2020 2:52 pm, edited 1 time in total.

User avatar
oRBIT2002
Posts: 634
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Coding a scrolltext

Post by oRBIT2002 » Fri Mar 06, 2020 1:58 pm

Yes I only have one split, but when I set a breakpoint in FCEUX I get a spritehit on different scanlines all the time.

lidnariq
Posts: 10276
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Coding a scrolltext

Post by lidnariq » Fri Mar 06, 2020 2:04 pm

The flag becomes set when sprite 0 collides with a background pixel. The flag becomes clear on scanline -1...

User avatar
tokumaru
Posts: 12003
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Coding a scrolltext

Post by tokumaru » Fri Mar 06, 2020 4:13 pm

The proper way to wait for a Sprite 0 hit is to first wait for the flag to be clear, then wait for it to be set:

Code: Select all

WaitForNoHit:
  bit $2002
  bvs WaitForNoHit
WaitForHit:
  bit $2002
  bvc WaitForHit
The PPU automatically clears the Sprite 0 hit flag at the beginning of each frame, so you first have to wait for that to happen before waiting for the next Sprite 0 hit.

User avatar
oRBIT2002
Posts: 634
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Coding a scrolltext

Post by oRBIT2002 » Sat Mar 07, 2020 3:52 am

Thanks, think I got that working. However I'm getting gfx-glitches when reading joypad in NMI now, don't really understand why at the moment. Could reading/writing $4016 during vblank cause gfx-issues in some way?

User avatar
tokumaru
Posts: 12003
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Coding a scrolltext

Post by tokumaru » Sat Mar 07, 2020 12:04 pm

oRBIT2002 wrote:
Sat Mar 07, 2020 3:52 am
Could reading/writing $4016 during vblank cause gfx-issues in some way?
Reading the controllers doesn't affect the PPU at all. It must be a timing issue. Are you just reading the controllers or also running a bunch of logic during vblank? Are you doing this before or after all the PPU-related tasks (including setting the scroll)?

User avatar
oRBIT2002
Posts: 634
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Coding a scrolltext

Post by oRBIT2002 » Sat Mar 07, 2020 2:18 pm

Here's my joypad loop at the moment. It have it in my NMI but it doesn't seem to matter where I put it, I get screen glitches here and there. When I unroll the loop (lda $4016, sta xxx, lda $4016, sta xx etc.), the glitches are gone.

Code: Select all

ReadGamepad:		ldx #1
				stx $4016
				dex
				stx $4016
				txa
				ldy #8
ReadGamePadLoop:	pha
				lda $4016
				lsr
				pla
				rol
				dey
				bne ReadGamePadLoop
				rts

User avatar
tokumaru
Posts: 12003
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Coding a scrolltext

Post by tokumaru » Sat Mar 07, 2020 6:46 pm

That doesn't make much sense... What's your main loop doing when the NMI fires? Are you backing up A, X and Y at the beginning of the NMI handler and restoring them at the end?

User avatar
oRBIT2002
Posts: 634
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Coding a scrolltext

Post by oRBIT2002 » Sun Mar 08, 2020 5:39 am

I'm waiting for a sprite0 hit, and yes I'm preserving/restoring registers in the NMI

User avatar
tokumaru
Posts: 12003
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Coding a scrolltext

Post by tokumaru » Sun Mar 08, 2020 7:52 am

Then I have no idea what could be wrong. Without seeing more code, I'm out of guesses...

User avatar
oRBIT2002
Posts: 634
Joined: Sun Mar 19, 2006 3:06 am
Location: Gothenburg/Sweden

Re: Coding a scrolltext

Post by oRBIT2002 » Mon Mar 09, 2020 12:00 am

Seems my NMI code sometimes "spills" into the frame that's probably causing gfx-glitches. These clockcycles are going fast, I really need more / scanline. :)
You really need to know what you're doing if you're coding stuff targeting full framerate!
Well, time for some optimizing. :)

Post Reply