It is currently Sun Dec 17, 2017 6:36 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 44 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: Mon Apr 24, 2017 4:03 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 221
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.


Top
 Profile  
 
PostPosted: Mon Apr 24, 2017 4:10 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10171
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Mon Apr 24, 2017 4:12 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5899
Location: Canada
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.


Top
 Profile  
 
PostPosted: Mon Apr 24, 2017 4:17 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10171
Location: Rio de Janeiro - Brazil
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?


Top
 Profile  
 
PostPosted: Mon Apr 24, 2017 4:30 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19354
Location: NE Indiana, USA (NTSC)
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.


Top
 Profile  
 
PostPosted: Mon Apr 24, 2017 5:38 pm 
Offline
User avatar

Joined: Mon Apr 24, 2017 5:52 am
Posts: 30
Location: West Allis, WI
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:
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.


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 4:29 am 
Offline
User avatar

Joined: Mon Apr 24, 2017 5:52 am
Posts: 30
Location: West Allis, WI
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.


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 4:32 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7320
Location: Chexbres, VD, Switzerland
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.


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 5:19 am 
Offline
User avatar

Joined: Mon Apr 24, 2017 5:52 am
Posts: 30
Location: West Allis, WI
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:
  DEC <ScrollY
  BIT $2002
  LDA <ScrollY
  STA $2005
  LDA #$00
  STA $2005


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 5:51 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10171
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 6:06 am 
Offline
User avatar

Joined: Mon Apr 24, 2017 5:52 am
Posts: 30
Location: West Allis, WI
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:
  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?


Last edited by JWinslow23 on Tue Apr 25, 2017 6:18 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 6:18 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7320
Location: Chexbres, VD, Switzerland
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.


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 6:22 am 
Offline
User avatar

Joined: Mon Apr 24, 2017 5:52 am
Posts: 30
Location: West Allis, WI
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. :?


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 7:24 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19354
Location: NE Indiana, USA (NTSC)
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


Top
 Profile  
 
PostPosted: Tue Apr 25, 2017 7:41 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7320
Location: Chexbres, VD, Switzerland
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 44 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC - 7 hours


Who is online

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