Uber noob question on button presses

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
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Uber noob question on button presses

Post by mantanz »

Hey folks,

So I have my ship shooting... sort of... but when I press and hold the button down the bullet resets to the ship position as it should but it stays there for as long as the button is held down...

I'm using the movement code from Nerdy Nights and it works great for my ship's movement but I'm not sure how I can detect the initial button press down rather than if it's being held down. Sorry if I'm not explaining this well but here's my code. I have another label elsewhere that handles the bullet's movement.

Code: Select all

LatchController:
	LDA #$01
	STA $4016
	LDA #$00
	STA $4016       ; tell both the controllers to latch buttons

; A button
ReadA:
	LDA $4016       	; player 1 button A
	AND #%00000001  	; only look at bit 0
	BEQ ReadADone	; branch to ReadADone if button is NOT pressed (0)
	LDX $0217       ; load ship sprite X position
	STX $021B       ; move bullet to ship sprite X position
	LDX $0214       ; load ship sprite y position
	DEX		      ; Move up a few pixels to align with ship
	DEX
	DEX
	STX $0218       ; move bullet to ship sprite Y position
ReadADone:	      ; handling this button is done
EDIT: I'll try throwing in another variable... maybe set a value when button is pressed and reset it when the bullet hits the wall or enemy. That way I can check it when the button is held and only reset the bullet when the values match. Man I miss bools. LOL
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Uber noob question on button presses

Post by thefox »

You need to save the buttons state from the previous frame. Then simply compare: "if previous=0 AND current=1 => button has been pressed after previously being down".

Some related links:
viewtopic.php?f=2&t=14809&p=179274#p179274
viewtopic.php?f=10&t=12456&p=142434#p142434
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Uber noob question on button presses

Post by dougeff »

In neslib, it does this, after polling for new buttons...
;gets the current buttons, first, then it...
sta <PAD_STATE,y ;stores it
tax ;temp store
eor <PAD_STATEP,y ;any bits same as last frame, flip
and <PAD_STATE ,y ;mask only new presses
sta <PAD_STATET,y ;this is only the new buttons
txa ;restore from temp
sta <PAD_STATEP,y ;save again for next frame

I would have done this differently, but the important part is the EOR/AND to get only button presses new to the frame.
Last edited by dougeff on Mon Jul 31, 2017 5:26 am, edited 2 times in total.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Uber noob question on button presses

Post by mantanz »

thefox wrote:You need to save the buttons state from the previous frame. Then simply compare: "if previous=0 AND current=1 => button has been pressed after previously being down".

Some related links:
viewtopic.php?f=2&t=14809&p=179274#p179274
viewtopic.php?f=10&t=12456&p=142434#p142434
Awesome, thanks!
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Uber noob question on button presses

Post by mantanz »

Nope still stuck... I cant work out how to check the state of the button on the last frame... I've found a few C examples and asm examples that are using defines but I have no idea what those defines are...

How do I go about this in NESASM3?

I know the bit I need to check but I'm not sure how to store it and check it on the next frame.

Any more help greatly appreciated :)

Edit: Oh I just saw your reply, Doug. I think I know what to do now :)

Edit again: Still stuck - I'm confused as to what PAD_STATE, PAD_STATET and PAD_STATEP are?
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Uber noob question on button presses

Post by dougeff »

Well, those are specific to shiru's code (neslib). It might be easier just to skip that for now, since you're working from nerdy nights.

Typically, you would read all buttons, and store them in a RAM address, for later retrieval.

I wrote about that here...
viewtopic.php?f=10&t=15684&p=191556
...near the bottom of the page.

There's also example code on the wiki...
http://wiki.nesdev.com/w/index.php/Controller_Reading

A simple way to store the last frame, is to copy the button presses to a second RAM address, just before reading the buttons again. Something like...

LDA controller1
STA controller1_last_frame
LDA controller2
STA controller2_last_frame
JSR read_controller

where these labels are all RAM locations.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Uber noob question on button presses

Post by mantanz »

Great, I was on the right track. Will have a go tonight after work. Thanks again for your help!
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Uber noob question on button presses

Post by mantanz »

Okay, I've made some progress. Sorry, I'm pretty dumb when it comes to this stuff!

I have my shooting working but it works when I press as well as release the button now, so I get two bullets with every press and release. lol . Here's my code:

Code: Select all

; A button
ReadA:
	LDA joypad       			; player 1 button A
	AND #%00000001  			; only look at bit 0 - clear all other bits
	CMP button_a_lastframe		; compare a with button state of last frame 
	BEQ ReadADone				; branch to ReadADone if button is NOT pressed (0)
	LDX $0217       			; load ship sprite X position
	INX							; Offset a few pixels
	INX
	INX
	INX
	INX
	INX
	INX
	STX player_bullet_x       	; move bullet to ship sprite X position
	LDX $0214       			; load ship sprite y position
	DEX							; Move up a few pixels to align with ship
	DEX
	DEX
	STX player_bullet_y       	; save bullet y pos to ship sprite y position
	STA button_a_lastframe		; Store button press state to use next frame
ReadADone:						; handling this button is done
Now I understand what's happening here... I think. Basically this code checks if the state of the button matches the state of the button last frame... problem is if the button is released then it will match, just like it does on initial press. What's an easy way to ignore button release? I have tried comparing with zero but nothing seems to work...

I did look over other examples but there were quite a few opcodes I just done't understand yet (I will though). I got the gist though, which is how I came up with this.

EDIT: I'm an idiot - BEQ means branch if equal to zero, doesn't it? I was thinking it meant if the two values compared were equal...
EDIT AGAIN: Nope - I was right first time. I'm getting zero confuded with zero flag, right? If the data and registers match, the zero flag is set. I think?
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Uber noob question on button presses

Post by lidnariq »

mantanz wrote:EDIT: I'm an idiot - BEQ means branch if equal to zero, doesn't it? I was thinking it meant if the two values compared were equal...
EDIT AGAIN: Nope - I was right first time. I'm getting zero confuded with zero flag, right? If the data and registers match, the zero flag is set. I think?
It means both!

Testing for equality is achieved by subtracting two numbers, setting the flags appropriately, and then throwing away the actual result. (The CMP, CPX, and CPY instructions). So you get the N, C, and V bits set appropriate, which is what the various Bxx instructions care about.
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Uber noob question on button presses

Post by mantanz »

lidnariq wrote:
mantanz wrote:EDIT: I'm an idiot - BEQ means branch if equal to zero, doesn't it? I was thinking it meant if the two values compared were equal...
EDIT AGAIN: Nope - I was right first time. I'm getting zero confuded with zero flag, right? If the data and registers match, the zero flag is set. I think?
It means both!

Testing for equality is achieved by subtracting two numbers, setting the flags appropriately, and then throwing away the actual result. (The CMP, CPX, and CPY instructions). So you get the N, C, and V bits set appropriate, which is what the various Bxx instructions care about.
Aah. So I used BCS and now it only fires when I release the button. FML. LOL

EDIT: This is driving me nuts. Getting to the point I'd rather pay someone to fix it. LOL
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Uber noob question on button presses

Post by mantanz »

WOOHOO!

I got it working. Probably not the nuicest code and if anyone has any ideas how to streamline It'd be much appreciated but hell, it works!

Code: Select all

; A button
ReadA:
	LDA joypad       			; player 1 button A
	AND #%00000001  			; only look at bit 0 - clear all other bits
	CMP joypad_lastframe		; compare A with button state of last frame
	BEQ ReadADone				; branch to ReadADone if button is NOT pressed (0)
	CMP #$0000
	BEQ ReadADone
	LDX $0217       			; load ship sprite X position
	INX							; Offset a few pixels
	INX
	INX
	INX
	INX
	INX
	INX
	STX player_bullet_x       	; move bullet to ship sprite X position
	LDX $0214       			; load ship sprite y position
	DEX							; Move up a few pixels to align with ship
	DEX
	DEX
	STX player_bullet_y       	; save bullet y pos to ship sprite y position
	;STA joypad_lastframe
ReadADone:						; handling this button is done
	STA joypad_lastframe		; S
tore button press state to use next frame
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Uber noob question on button presses

Post by tokumaru »

Since there may be many actions triggered by buttons being pressed, as well as actions triggered by buttons being held down, the common thing to do is to dedicate one variable for button states in each of those situations, so you can check them as many times as necessary during the frame, as opposed to doing comparisons against the previous state on a case-by-case basis. This is a simpler approach:

Code: Select all

  lda joypad_down
  sta joypad_previous ;remember the old joypad state
  jsr ReadJoypad ;update joypad_down
  lda joypad_previous ;get the old joypad state
  eor #$ff ;invert all the bits, so that pressed buttons = 0
  and joypad_down ;turn any buttons that were already pressed into 0s
  sta joypad_pressed ;whatever buttons remain as 1s are new
Now you can trigger actions based either on joypad_down (e.g. walking) or joypad_pressed (e.g. shooting), depending on whether you want continuous reactions or not. For shooting you could do:

Code: Select all

  lda joypad_pressed
  and #JOYPAD_A
  beq FiringDone
  ;(fire a shot here)
FiringDone:
No need for comparing button states here, since you already have a variable indicating all buttons that weren't pressed last frame but are pressed now.
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Uber noob question on button presses

Post by mantanz »

Wow thanks! That helps heaps. I was wondering how to inverse the bits too. Cheers :)
Post Reply