Tips on best coding practices?
Moderator: Moderators
Re: Tips on best coding practices?
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.
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?
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.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
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Tips on best coding practices?
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.)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.
Edit: tokumaru already covered it.
Re: Tips on best coding practices?
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?
Or by reading input only after DMA to OAM. In lag frames, the flag for "display list is ready" won't be set.tokumaru wrote: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.pubby wrote:Nowadays people put controller reads immediately after sprite DMA in order to prevent a glitch related to DPCM sounds.
- JWinslow23
- Posts: 30
- Joined: Mon Apr 24, 2017 5:52 am
- Location: West Allis, WI
Re: Tips on best coding practices?
Yes, I do do this.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.
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
Did that, and it works. Thanks!tokumaru wrote:stuff that does things in places
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.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.
- JWinslow23
- Posts: 30
- Joined: Mon Apr 24, 2017 5:52 am
- Location: West Allis, WI
Re: Tips on best coding practices?
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.
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?
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.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.
As how to make a repeating BG scroll it's extremely simple, you use the $2000 and $2005 registers to do that.
- JWinslow23
- Posts: 30
- Joined: Mon Apr 24, 2017 5:52 am
- Location: West Allis, WI
Re: Tips on best coding practices?
Bregalad wrote: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.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.
As how to make a repeating BG scroll it's extremely simple, you use the $2000 and $2005 registers to do that.
Code: Select all
DEC <ScrollY
BIT $2002
LDA <ScrollY
STA $2005
LDA #$00
STA $2005
Re: Tips on best coding practices?
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.
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.
- JWinslow23
- Posts: 30
- Joined: Mon Apr 24, 2017 5:52 am
- Location: West Allis, WI
Re: Tips on best coding practices?
Well, the writes are how they're supposed to be. I gotta be less stupid in variable naming, that should be ScrollX (horizontal scrolling) . 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.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.
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:
Last edited by JWinslow23 on Tue Apr 25, 2017 6:18 am, edited 1 time in total.
Re: Tips on best coding practices?
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.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.
If you need to move the screen down by 16 pixels, use the value $e0 instead.
- JWinslow23
- Posts: 30
- Joined: Mon Apr 24, 2017 5:52 am
- Location: West Allis, WI
Re: Tips on best coding practices?
Not working. The screen is blank if I use $E0 for some reason.Bregalad wrote: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.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.
If you need to move the screen down by 16 pixels, use the value $e0 instead.
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?
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
EDIT: corrected brain fart
Re: Tips on best coding practices?
$2000 not $2001. That or simply use vertical mirroring / horizontal arrangement.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.