Page 2 of 3

Re: Tips on best coding practices?

Posted: Mon Apr 24, 2017 4:03 pm
by pubby
Nowadays people put controller reads immediately after sprite DMA in order to prevent a glitch related to DPCM sounds. See: https://wiki.nesdev.com/w/index.php/Con ... ng_OAM_DMA

You don't have to understand what those words mean in order to use it. Just copy/paste the code from the wiki into your NMI subroutine.

Re: Tips on best coding practices?

Posted: Mon Apr 24, 2017 4:10 pm
by tokumaru
pubby wrote:Nowadays people put controller reads immediately after sprite DMA in order to prevent a glitch related to DPCM sounds. See: https://wiki.nesdev.com/w/index.php/Con ... ng_OAM_DMA
That could present a problem if done in the NMI and the logic in a lag frame samples different controller states. You can easily solve that if you just copy the controller state to a secondary variable to be used for game logic at the beginning of the game loop though.

Re: Tips on best coding practices?

Posted: Mon Apr 24, 2017 4:12 pm
by rainwarrior
pubby wrote:Nowadays people put controller reads immediately after sprite DMA in order to prevent a glitch related to DPCM sounds. See: https://wiki.nesdev.com/w/index.php/Con ... ng_OAM_DMA

You don't have to understand what those words mean in order to use it. Just copy/paste the code from the wiki into your NMI subroutine.
It's a valid way to prevent the DPCM glitch but it's not always appropriate to read your controller in the NMI. (ilag frames leading to inconsistent state throughout the update, missed button presses, etc.)

Edit: tokumaru already covered it.

Re: Tips on best coding practices?

Posted: Mon Apr 24, 2017 4:17 pm
by tokumaru
I said you could easily solve the problem using a secondary variable but I didn't really spend much time thinking about all the implications of that. Missed button presses could happen either way I suppose. Is there anything else that could go wrong in that case?

Re: Tips on best coding practices?

Posted: Mon Apr 24, 2017 4:30 pm
by tepples
tokumaru wrote:
pubby wrote:Nowadays people put controller reads immediately after sprite DMA in order to prevent a glitch related to DPCM sounds.
That could present a problem if done in the NMI and the logic in a lag frame samples different controller states. You can easily solve that if you just copy the controller state to a secondary variable to be used for game logic at the beginning of the game loop though.
Or by reading input only after DMA to OAM. In lag frames, the flag for "display list is ready" won't be set.

Re: Tips on best coding practices?

Posted: Mon Apr 24, 2017 5:38 pm
by JWinslow23
Sumez wrote:Absolutely. You can easily store all 8 button states on a single NES controller in a single byte, with each bit indicating wether the button is pressed. I also do comparisons with the previous NMI to see if a button was just pressed to trigger events on button pulses (such as attacking or jumping), and store those in a separate byte.
Yes, I do do this.

Code: Select all

ReadJoypad:
  LDA <ButtonsHeldNow
  STA <ButtonsHeldLastFrame ; Store ButtonsHeldNow into ButtonsHeldLastFrame
  LDA #$01
  STA $4016             ; Continuously reload the buttons
  STA <ButtonsHeldNow   ; Initialize ButtonsHeldNow
  LSR A
  STA $4016             ; Stop reloading; ready to read controller
JoypadLoop:
  LDA $4016
  LSR A                 ; Store button state into carry
  ROL <ButtonsHeldNow   ; Rotate carry into ButtonsHeldNow
  BCC JoypadLoop        ; Carry will be 1 once all buttons are read
                        ; So jump back if carry is 0
  RTS                   ; Return
tokumaru wrote:stuff that does things in places
Did that, and it works. Thanks!
pubby wrote:Nowadays people put controller reads immediately after sprite DMA in order to prevent a glitch related to DPCM sounds. See: https://wiki.nesdev.com/w/index.php/Con ... ng_OAM_DMA

You don't have to understand what those words mean in order to use it. Just copy/paste the code from the wiki into your NMI subroutine.
As I don't use DPCM sounds (yet; I might possibly have a title scream or something), I'm just not going to bother with that. Besides, my controller routine will only read the first controller (this will be a one player game), and it also stores the last button held, so I'm not sure what that does to the cycles.

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 4:29 am
by JWinslow23
Bump.

Right now, I want to be able to add scrolling to this game. I'm a bit confused by the docs over at the NESDev Wiki, I'm not exactly sure what to do. How do I actually make the background scroll? I'll be scrolling horizontally, and the background repeats, if that helps.

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 4:32 am
by Bregalad
JWinslow23 wrote:Bump.

Right now, I want to be able to add scrolling to this game. I'm a bit confused by the docs over at the NESDev Wiki, I'm not exactly sure what to do. How do I actually make the background scroll? I'll be scrolling horizontally, and the background repeats, if that helps.
The scrolling pages on the wiki are currently being reworked, currently they are a bit messed up. They'll be fixed in the near future.

As how to make a repeating BG scroll it's extremely simple, you use the $2000 and $2005 registers to do that.

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 5:19 am
by JWinslow23
Bregalad wrote:
JWinslow23 wrote:Bump.

Right now, I want to be able to add scrolling to this game. I'm a bit confused by the docs over at the NESDev Wiki, I'm not exactly sure what to do. How do I actually make the background scroll? I'll be scrolling horizontally, and the background repeats, if that helps.
The scrolling pages on the wiki are currently being reworked, currently they are a bit messed up. They'll be fixed in the near future.

As how to make a repeating BG scroll it's extremely simple, you use the $2000 and $2005 registers to do that.
...use them how? That's my question. :P OK, I've made the screen "scroll" horizontally, but it seems that the background has also been shifted up 2 rows (when my ScrollX is always 0). What do I do to remedy this? Here is my code that handles scrolling (with .inesmir 0 as the mode):

Code: Select all

  DEC <ScrollY
  BIT $2002
  LDA <ScrollY
  STA $2005
  LDA #$00
  STA $2005

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 5:51 am
by tokumaru
You appear to have switched X and Y there... The first $2005 write sets the horizontal scroll (X) while the second write sets the vertical scroll (Y).

Note that depending on the NT mirroring you're using, the total background size will be either 256x480 pixels (horizontal mirroring) or 512x240 pixels (vertical mirroring), meaning that one of the scroll values can't be represented in just 8 bits (8 bits can only go up to 255, but you need to go up to 479 or 511). For this reason, in addition to writing to $2005, you need to update the "9th bit" of the scroll values using register $2000 (the lower 2 bits).

If the background is supposed to be the same 256x480 or 512x240 area over and over, simply changing the scroll registers will do, but if you want to display a larger background, such as a level in SMB, you'll need to progressively update the name tables each vblank in coordination with the scroll changes.

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 6:06 am
by JWinslow23
tokumaru wrote:You appear to have switched X and Y there... The first $2005 write sets the horizontal scroll (X) while the second write sets the vertical scroll (Y).

Note that depending on the NT mirroring you're using, the total background size will be either 256x480 pixels (horizontal mirroring) or 512x240 pixels (vertical mirroring), meaning that one of the scroll values can't be represented in just 8 bits (8 bits can only go up to 255, but you need to go up to 479 or 511). For this reason, in addition to writing to $2005, you need to update the "9th bit" of the scroll values using register $2000 (the lower 2 bits).

If the background is supposed to be the same 256x480 or 512x240 area over and over, simply changing the scroll registers will do, but if you want to display a larger background, such as a level in SMB, you'll need to progressively update the name tables each vblank in coordination with the scroll changes.
Well, the writes are how they're supposed to be. I gotta be less stupid in variable naming, that should be ScrollX (horizontal scrolling) :P . And the background will simply be repeating, as in my original two games. The problem here is, there seem to be two blank rows of background appearing now that weren't there earlier. I've "fixed" it by setting the scroll y to always equal $F0, but I'm sure there's a better way.

What I have now seems to work for my purposes, but to do this "correctly", how would I change $2000? I'm trying this:

Code: Select all

  LDA <ScrollX
  BEQ NoWrap
  LDA $2000
  EOR #%00000001
  STA $2000
NoWrap:
This is supposed to toggle the X>256 bit of $2000 every time the scroll x is 0, but this is causing the sprite to render incorrectly. How would I fix this?

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 6:18 am
by Bregalad
JWinslow23 wrote: The problem here is, there seem to be two blank rows of background appearing now that weren't there earlier. I've "fixed" it by setting the scroll y to always equal $F0, but I'm sure there's a better way.
You should explain your problem better. $f0 is a "negative" vertical scroll value and you should avoid it as it will show attribute table data as name table data. This should make 16 glitchy lines at the top of the screen, although 8 will be hidden by overscan so 8 will show.

If you need to move the screen down by 16 pixels, use the value $e0 instead.

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 6:22 am
by JWinslow23
Bregalad wrote:
JWinslow23 wrote: The problem here is, there seem to be two blank rows of background appearing now that weren't there earlier. I've "fixed" it by setting the scroll y to always equal $F0, but I'm sure there's a better way.
You should explain your problem better. $f0 is a "negative" vertical scroll value and you should avoid it as it will show attribute table data as name table data. This should make 16 glitchy lines at the top of the screen, although 8 will be hidden by overscan so 8 will show.

If you need to move the screen down by 16 pixels, use the value $e0 instead.
Not working. The screen is blank if I use $E0 for some reason.

The thing is, I'm thinking $00 should work and show the whole screen, but even in NTSC mode, there seem to be blank rows on the bottom that don't show up without the scrolling code. This is confusing to me. :?

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 7:24 am
by tepples
If Y=224 ($E0) blanks the screen, then you probably have the cartridge set to 256x480 (aka vertical arrangement or horizontal mirroring), and it's reading the wrong nametable. Try setting bit 1 of the value you write to $2000, that is, ORing it with the value $02.


EDIT: corrected brain fart

Re: Tips on best coding practices?

Posted: Tue Apr 25, 2017 7:41 am
by Bregalad
tepples wrote:If Y=224 ($E0) blanks the screen, then you probably have the cartridge set to 256x480 (aka vertical arrangement or horizontal mirroring), and it's reading the wrong nametable. Try setting bit 1 of the value you write to $2001, that is, ORing it with the value $02.
$2000 not $2001. That or simply use vertical mirroring / horizontal arrangement.