Controller press "lasting too long" and being read multiple frames

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
samcan
Posts: 13
Joined: Fri May 29, 2020 9:06 pm

Controller press "lasting too long" and being read multiple frames

Post by samcan » Sat Jun 06, 2020 2:51 pm

Hi,

I apologize if I called this the wrong thing and couldn't find it on the forums or the wiki. Right now, my code has a state variable which keeps track of which screen has been loaded. When the user presses Start, it should then advance to the next state (and hence screen). But what's happening is that when the user presses Start, it's loads each state one after another until it reaches the end. It's correctly loading the intermediate states as you can see them flash by.

I thought of inserting a lag on the second state before it then reads input from the controller, where it counted down a number. I tried both 60 and 120, but it's not consistently long enough, and it feels kludgy.

Is there a better way to do this that I'm not thinking of?

Thanks!

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

Re: Controller press "lasting too long" and being read multiple frames

Post by lidnariq » Sat Jun 06, 2020 2:55 pm

Check for the controller changing from "not pressed" to "pressed". That is, keep track of the previous read's state.

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

Re: Controller press "lasting too long" and being read multiple frames

Post by tokumaru » Sat Jun 06, 2020 3:08 pm

What you need in this case is to detect state transitions, rather than the immediate state of the buttons. In order to detect OFF->ON transitions, you need to use the previous controller state as a mask to erase from the current state any buttons that were already pressed before:

Code: Select all

lda PreviousState ;state of the buttons last frame
eor #$ff ;turn pressed buttons into 0s
and CurrentState ;clear those buttons in the current state
sta NewButtons ;save this for all OFF->ON transition needs
Now you can just test NewButtons instead of CurrentState whenever an action in your game needs to react to button presses only once (e.g. menu selections, jumping, shooting, etc.).

samcan
Posts: 13
Joined: Fri May 29, 2020 9:06 pm

Re: Controller press "lasting too long" and being read multiple frames

Post by samcan » Sat Jun 06, 2020 5:19 pm

So I modified my ReadController1 subroutine; my thought process was that if I mask out the previously pressed buttons in the subroutine, and then copy the resulting output to buttons1, I don't need to change any of the other code that handles input. But, pressing Start still sends me flying through the screens.

prevbtns is the variable storing the previously pressed buttons, newbtns is the variable storing the newly pressed buttons, and buttons1 is the output variable.

Code: Select all

;;;;;;;;;;;;;;;
ReadController1:
  ; set the old buttons1 as the prevbtns
  LDA buttons1
  STA prevbtns

  ; get controller input and store in newbtns
  LDA #$01
  STA $4016
  LDA #$00
  STA $4016
  LDX #$08
@loop:
  LDA $4016
  LSR A            ; bit0 -> Carry
  ROL newbtns     ; bit0 <- Carry
  DEX
  BNE @loop

  ; NEW CODE FOLLOWS
  ; http://forums.nesdev.com/viewtopic.php?f=10&t=20150#p250630
  ; to eliminate input being read multiple times, we need to subtract
  ; out previous input
  LDA prevbtns
  EOR #$FF
  AND newbtns
  STA buttons1
  
  RTS
  

samcan
Posts: 13
Joined: Fri May 29, 2020 9:06 pm

Re: Controller press "lasting too long" and being read multiple frames

Post by samcan » Sat Jun 06, 2020 5:29 pm

Hmmm, I'm looking at the sample code from http://wiki.nesdev.com/w/index.php/Cont ... d_Releases and will report back...

samcan
Posts: 13
Joined: Fri May 29, 2020 9:06 pm

Re: Controller press "lasting too long" and being read multiple frames

Post by samcan » Sat Jun 06, 2020 5:38 pm

So I'm getting the same results...

In Mesen's debugger, setting the Start button to input, it appears that it's setting the buttons1 to Start, then on the next frame it sets it to off, and then on the next frame sets it to Start, and so on, and so my screen change routines are still getting called.

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

Re: Controller press "lasting too long" and being read multiple frames

Post by lidnariq » Sat Jun 06, 2020 5:43 pm

Don't copy "buttons1" (which is your "these buttons were pressed anew") but instead copy "newbtns" (which is your "this is the state for this frame")

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

Re: Controller press "lasting too long" and being read multiple frames

Post by tokumaru » Sat Jun 06, 2020 6:30 pm

Yeah, it's newbtns you have to copy to prevbtns. buttons1 is something you calculate for your convenience, but the real state of the controller is still newbtns.

samcan
Posts: 13
Joined: Fri May 29, 2020 9:06 pm

Re: Controller press "lasting too long" and being read multiple frames

Post by samcan » Sat Jun 06, 2020 6:59 pm

lidnariq wrote:
Sat Jun 06, 2020 5:43 pm
Don't copy "buttons1" (which is your "these buttons were pressed anew") but instead copy "newbtns" (which is your "this is the state for this frame")
Yes, that worked. Thanks!

For reference, here's my working ReadController1 subroutine:

Code: Select all

;;;;;;;;;;;;;;;
ReadController1:
  LDA newbtns
  STA prevbtns

  LDA #$01
  STA $4016
  LDA #$00
  STA $4016
  LDX #$08
@loop:
  LDA $4016
  LSR A            ; bit0 -> Carry
  ROL newbtns     ; bit0 <- Carry
  DEX
  BNE @loop

  ; http://forums.nesdev.com/viewtopic.php?f=10&t=20150#p250630
  ; to eliminate input being read multiple times, we need to subtract
  ; previously-pressed buttons
  LDA prevbtns
  EOR #$FF
  AND newbtns
  STA buttons1
  RTS

Post Reply