It is currently Sun Dec 17, 2017 4:37 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Stable background
PostPosted: Mon Sep 22, 2014 2:44 pm 
Offline

Joined: Mon Sep 22, 2014 2:41 pm
Posts: 2
I've tried to create a stable background, but it is not possible. It flickers and moves around.

I write to 0, 0 to $2005 and during the frame I update the background by writing to $2006 and $2007. Any help is appreciated!


Top
 Profile  
 
 Post subject: Re: Stable background
PostPosted: Mon Sep 22, 2014 3:17 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19354
Location: NE Indiana, USA (NTSC)
$2005 and $2006 share an internal register inside the PPU. When you do updates through $2006/$2007, you overwrite this register. So after you update video memory, you need to set $2005 again before the next frame begins.


Top
 Profile  
 
 Post subject: Re: Stable background
PostPosted: Mon Sep 22, 2014 3:46 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3192
Location: Mountain View, CA, USA
Reference material for tepples' statements:

http://wiki.nesdev.com/w/index.php/PPU_scrolling
http://wiki.nesdev.com/w/index.php/The_ ... _scrolling

The short version is: do your lda #0 / sta $2005 / sta $2005 after you do all of your $2006/$2007 updates, and before the start of the next frame (e.g. do all that within NMI).


Top
 Profile  
 
 Post subject: Re: Stable background
PostPosted: Mon Sep 22, 2014 5:35 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5899
Location: Canada
To clarify, koitsu means before the start of rendering, which begins at the end of the vertical blank. Vertical blank starts at the beginning of NMI, and lasts for a short period of time, during which you need to make all needed writes to $2007, then write to $2005 twice to set your scroll position.

If all of this is not done before your reach the end of the vertical blank, you will have visual problems, i.e. some of the $2007 writes will go to unexpected addresses (nametable corruption), and the scroll will be wrong.


Top
 Profile  
 
 Post subject: Re: Stable background
PostPosted: Tue Sep 23, 2014 1:34 pm 
Offline

Joined: Mon Sep 22, 2014 2:41 pm
Posts: 2
Thanks for your help!

Should I poll for the vertical blank? Or do the rendering in some other way?


Top
 Profile  
 
 Post subject: Re: Stable background
PostPosted: Tue Sep 23, 2014 3:02 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10169
Location: Rio de Janeiro - Brazil
piot wrote:
Should I poll for the vertical blank?

You can poll a flag that you set in the NMI, but not $2002. Reading bit 7 of $2002 is not advised is because when the register is read at the exact same time the flag gets set by the PPU, the flag gets cleared immediately and never returns a 1. This particular alignment has reasonably high chances of happening, since the register is read in a loop. This will cause you to miss VBlanks from time to time, which will affect the smoothness of animations and sounds.

Quote:
Or do the rendering in some other way?

The absolute simplest way is to keep NMIs always enabled and have the NMI handler only change a variable, nothing more:
Code:
NMI:
   inc FrameCount
   rti

Then, whenever you want to wait for Vblank, you do this:
Code:
   ;wait for VBlank
   lda FrameCount
Wait:
   cmp FrameCount
   beq Wait

The idea is that you put the current frame counter into the accumulator and keep comparing it to the memory location it was loaded from. The values will remain equal until the NMI fires and modifies the variable in RAM, which will cause the loop to end.

NMIs are 100% reliable, and you won't miss VBlanks with this technique as long as your game logic doesn't take longer than a full NES frame to execute.

The simplest NES game structure that's still versatile for a wide variaty of game types goes something like this:
Code:
InitializeModule:

   ;SET UP EVERYTHING FOR THE FOLLOWING LOOP;

ProcessFrame:

   ;READ CONTROLLERS;
   
   ;GAME LOGIC (PHYSICS, AI, SCROLLING, ETC.);

   ;WAIT FOR VBLANK;

   ;WRITE DATA TO THE PPU, RESET THE SCROLL, ETC;
   
   ;CALL MUSIC DRIVER;

   jmp ProcessFrame

You can have multiple blocks like this in your NES program, one for each different "module". For example, the title screen and the menus would use one loop like this where the logic is basically moving cursors around and updating options on screen according to user input. Once the game starts, another loop like this will take care of updating backgrounds, moving objects around and so on. You can freely navigate from module to module by simply jumping to the initialization code of another module at any time.


Top
 Profile  
 
 Post subject: Re: Stable background
PostPosted: Wed Sep 24, 2014 6:44 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2983
Location: Tampere, Finland
tokumaru wrote:
NMIs are 100% reliable, and you won't miss VBlanks with this technique as long as your game logic doesn't take longer than a full NES frame to execute.

There is one tiny caveat, which I don't see people mentioning very often. Even if you use NMIs, the NMI will be suppressed from time to time if you poll on $2002 (for whatever reason) while the vblank flag is getting set. This is in addition to the vblank flag not being returned correctly from the $2002 read. This is nothing a newcomer should worry about, though.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
 Post subject: Re: Stable background
PostPosted: Wed Sep 24, 2014 9:46 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10169
Location: Rio de Janeiro - Brazil
thefox wrote:
Even if you use NMIs, the NMI will be suppressed from time to time if you poll on $2002 (for whatever reason) while the vblank flag is getting set.

True. The NMI flag perfectly supresses the need for reading the VBlank flag in $2002, but $2002 reads are still common for resetting the $2005/$2006 first/second write state. Personally, I never use $2002 for that, because I believe I have to make my code stable enough to ALWAYS write to $2005 and $2006 in pairs, otherwise my code has a bug that should be fixed. Still, even if you do use $2002 for this purpose, that will most likely be AFTER the detection of VBlank, and since you'll have already detected it there's no chance of missing it, so this isn't such a big issue.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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