Gamepad code: Difference between revisions
(→Reading pressed buttons: With the spread of the PowerPak and the discovery of why games reread the controller, I rewrote the lead graph about "real nes") |
m (→fixed a link) |
||
Line 80: | Line 80: | ||
If your code is intended to be used with [[APU DMC]] playback this code will need to be altered. The NES occasionally glitches the controller port twice in a row if sample playback is enabled, and games using samples need to work around this. For example, ''Super Mario Bros. 3'' reads each controller's 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. | If your code is intended to be used with [[APU DMC]] playback this code will need to be altered. The NES occasionally glitches the controller port twice in a row if sample playback is enabled, and games using samples need to work around this. For example, ''Super Mario Bros. 3'' reads each controller's 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 | The buttons byte ''buttons'' should be placed in zero page. | ||
<pre> | <pre> | ||
; we reserve one byte for storing the data that is read from controller | ; we reserve one byte for storing the data that is read from controller | ||
Line 87: | Line 87: | ||
</pre> | </pre> | ||
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*.''. | When reading from ''JOYPAD*'' what is read migh be different from $01/$00. See [[controller port registers|Controller Port]] for more information on that subject. In this code the only concern is bit 0 read from ''JOYPAD*.''. | ||
<pre> | <pre> | ||
JOYPAD1 = $4016 | JOYPAD1 = $4016 |
Revision as of 01:50, 1 March 2011
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 with APU DMC playback this code will need to be altered. The NES occasionally glitches the controller port twice in a row if sample playback is enabled, and games using samples need to work around this. For example, Super Mario Bros. 3 reads each controller's 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 zero page.
; 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