Sprite ram updates in main thread

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
casprog
Posts: 66
Joined: Fri Oct 28, 2016 12:37 pm

Sprite ram updates in main thread

Post by casprog » Mon Sep 10, 2018 8:44 am

Hi all,

Since I'm using DMA transfer during NMI my sprite data is technically already buffered, so is there any harm in updating sprite ram data (position, attributes, etc), in my main loop instead of within NMI?

The only possible risk I can think of is I may be making changes while the DMA process is active but I don't know if that is a bad thing on the NES?

I tried searching for a definitive answer on this but could not find it.

tepples
Posts: 21750
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Sprite ram updates in main thread

Post by tepples » Mon Sep 10, 2018 8:56 am

Mostly your main loop needs to set a flag in RAM that tells your NMI handler that the sprite list is filled and ready to push to OAM, and then have the NMI handler clear that flag. If the flag is not set, the NMI handler would skip pushing the list to OAM. Otherwise, during lag frames, your NMI handler could end up pushing a half-built list, causing visible artifacts.

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

Re: Sprite ram updates in main thread

Post by tokumaru » Mon Sep 10, 2018 9:58 am

casprog wrote:Since I'm using DMA transfer during NMI my sprite data is technically already buffered, so is there any harm in updating sprite ram data (position, attributes, etc), in my main loop instead of within NMI?
Not at all. That's actually the preferred way to do things: main thread handles game logic and buffers PPU updates (which includes the OAM buffer), and then the NMI handler flushes the buffers to VRAM/OAM. You just need to use a flag to indicate to the NMI handler when the buffered data is valid - you don't want to send half-ready data to VRAM.
The only possible risk I can think of is I may be making changes while the DMA process is active but I don't know if that is a bad thing on the NES?
That won't happen, because the CPU stays busy while the DMA transfer takes place, execution only continues when the transfer is done.

casprog
Posts: 66
Joined: Fri Oct 28, 2016 12:37 pm

Re: Sprite ram updates in main thread

Post by casprog » Mon Sep 10, 2018 12:08 pm

A-ha! thanks guys : )

Perfect, currently my NMI works with a PPU buffer and main thread updates sprite ram, so I just need to add the ready flag.

User avatar
koitsu
Posts: 4215
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Sprite ram updates in main thread

Post by koitsu » Mon Sep 10, 2018 12:28 pm

Not sure if it will matter to the OP, but doesn't doing this cause problems with PAL consoles? (That 3rd paragraph required me to read it about 6 times...)

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

Re: Sprite ram updates in main thread

Post by lidnariq » Mon Sep 10, 2018 12:42 pm

(I just edited that paragraph and moved it to the end of the section; hopefully it's clearer now. The entire rest of the section is only about the 2C02, so I thought it made sense to move this bit about the 2C07 to the end)

User avatar
koitsu
Posts: 4215
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Sprite ram updates in main thread

Post by koitsu » Mon Sep 10, 2018 1:37 pm

lidnariq wrote:(I just edited that paragraph and moved it to the end of the section; hopefully it's clearer now. The entire rest of the section is only about the 2C02, so I thought it made sense to move this bit about the 2C07 to the end)
Yes, this is much clearer -- thank you!

User avatar
rainwarrior
Posts: 7669
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Sprite ram updates in main thread

Post by rainwarrior » Mon Sep 10, 2018 3:56 pm

koitsu wrote:Not sure if it will matter to the OP, but doesn't doing this cause problems with PAL consoles? (That 3rd paragraph required me to read it about 6 times...)
The OP wasn't asking about doing the DMA during the main thread, so it's not really related to that problem, no.

Yes, please give that paragraph a copyedit/rewrite. I think I wrote it, but it was more of a first pass attempt to have the wiki describe the PAL situation at all.

casprog
Posts: 66
Joined: Fri Oct 28, 2016 12:37 pm

Re: Sprite ram updates in main thread

Post by casprog » Mon Sep 10, 2018 8:45 pm

I noticed a nice chunk of cycles saved adding the flag in, hovering around 1100 now under close to full load while processing my ppu buffer and redrawing sprites, and on average nmi is sitting around 99!

I added this at the end of my main thread, after my game logic runs:

Code: Select all

	
	; check if we should update dma
	LDA spriteram_updated	
	BEQ dma_check_done       
	LDA #$01
	STA perform_sprite_dma
	; reset spriteram update flag
	LDA #$00
	STA spriteram_updated
dma_check_done:	

Then during nmi:

Code: Select all

	LDA perform_sprite_dma
	BEQ sprite_dma_done
	LDA #$00
	STA $2003
	LDA #$02
	STA $4014
	; reset dma flag
	LDA #$00
	STA perform_sprite_dma
sprite_dma_done:	
The NMI routine is the only place which resets the dma flag and my main thread is the only place that turns it on. My sprite updates appear to be working correctly, does this solution seem OK?

Post Reply