Gamepad code

From NESdev Wiki
Revision as of 04:22, 13 June 2009 by Ndwiki (talk | contribs) (1 revision: Rest of pages not related to reference)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

For Nesasm

; Uncomment the next line if you want to have all your button callbacks to 
; execute upon "has gone from up to down" rather than "is currently down".
;EDGE_BUTTONS = 1
    .org 0x00
.ifdef EDGE_BUTTONS
buttons_down            .ds 8
.endifdef
current_button_sub      .ds 2

     .org 0x8000
; Need quite a bit of stuff here. See: [[Init code]]

get_buttons:
    lda #0x01 ; strobe
    sta 0x4016
    lda #0x00 ; MOAR strobe
    sta 0x4016
    ldx #0
.get_button:
    lda 0x4016
    and #0x01 ; Only want information about the first bit
; bne means branch on the zero register being false, which it
; will be if the number in the accumulator is non-zero.
    bne .pressed
    .ifdef EDGE_BUTTONS
    lda #0x00
    sta buttons_down, x
    .endifdef
    jmp .end
.pressed:
    .ifdef EDGE_BUTTONS
    lda buttons_down, x
    bne .end
    lda #0x01
    sta buttons_down, x
    .endifdef
    txa
    pha
    asl A
    tax
    lda button_subs + 0x00, x ; Equivalent to non-existent jsr (button_subs, x)
    sta current_button_sub + 0x00
    lda button_subs + 0x01, x
    sta current_button_sub + 0x01
    lda #HIGH(.after_button_sub + 0x01)
    pha
    lda #LOW(.after_button_sub + 0x01)
    pha
    jmp [current_button_sub]
.after_button_sub:
    pla
    tax
.end:
    txa
    inx
    cmp #8
    bmi .get_button
    jmp get_buttons

button_subs: ; Vector table
    .dw do_nothing ; a
    .dw do_nothing ; b
    .dw do_nothing ; select
    .dw do_nothing ; start
    .dw do_nothing ; up
    .dw do_nothing ; down
    .dw do_nothing ; left
    .dw do_nothing ; right

do_nothing:
    rts

For ca65

I am a big fan of structured code, so this coding style will be a bit different from the nesasm version above. This describes the nameless loops used in the code you see below.

Reading pressed buttons

If your code is intended to be used on a real NES this code will need to be altered. If a real nes is used the reading of controller data isn't as exact as one might like it to be. E.g. Super Mario Bros 3 reads each controllers data at least two times each frame. First it reads it as normal, then it reads it again. If the two results differ, it does the procedure all over.

The buttons byte buttons should be placed in Zeropage.

; we reserve one byte for storing the data that is read from controller
.zeropage
buttons .res 1

When reading from JOYPAD* what is read migh be different from $01/$00. See Controller Port for more information on that subject. In this code the only concern is bit 0 read from JOYPAD*..

JOYPAD1 = $4016
JOYPAD2 = $4017

This is the end result that will be stored in buttons. 1 if the button was pressed, 0 otherwise.

bit:   	7	6	5	4	3	2	1	0
button:	A	B	slct	strt	up	down	left	right

This subroutine takes 146 cycles to execute.

; we actually only need to strobe bit 0 so we're hitting
; two birds with one stone here (X=8 when the loop is entered)
readjoy:
	ldx	#09
	stx	JOYPAD1
	dex
	stx	JOYPAD1
:	lda	JOYPAD1
	lsr	a		; bit0 -> Carry
	rol	buttons		; bit0 <- Carry
	dex
	bne	:-
	rts