|
Tag: Redirect target changed |
(13 intermediate revisions by 4 users not shown) |
Line 1: |
Line 1: |
| ==For [[Nesasm]]==
| | #REDIRECT [[Controller reading]] |
| <pre>
| |
| ; 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
| |
| </pre>
| |
| | |
| ==For [[ca65]]==
| |
| I am a big fan of structured code, so this coding style will be a bit different from the nesasm version above. [http://www.cc65.org/doc/ca65-5.html#ss5.5 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 [[Zeropage]].
| |
| <pre>
| |
| ; we reserve one byte for storing the data that is read from controller
| |
| .zeropage
| |
| buttons .res 1
| |
| </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*.''.
| |
| <pre>
| |
| JOYPAD1 = $4016
| |
| JOYPAD2 = $4017
| |
| </pre>
| |
| | |
| This is the end result that will be stored in ''buttons''. '''1''' if the button was pressed, '''0''' otherwise.
| |
| <pre>
| |
| bit: 7 6 5 4 3 2 1 0
| |
| button: A B slct strt up down left right
| |
| </pre>
| |
| | |
| This subroutine takes 146 cycles to execute.
| |
| <pre>
| |
| ; 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
| |