== Controller Input ==

In this tutorial, you'll learn to read the joypad registers and react to player
input ;). We're going to need to store the player's input somewhere, so we'll
declare some variables in the system's RAM ($0000-$1FFF). If you make your own
variables later in this part of RAM, keep in mind that the stack is set to
$1FFF, so try not to get too close to that area (of course). We'll define
variables for both Controllers (aka joypads) 1 & 2.

Note: Up to 4 controllers can receive input through a multitap. You can expand
my code to do so yourself :P. There is a doc explaining this in the snesbase pack.

.ENUM $0000
Joy1Raw     DW      ; Holder of RAW joypad data from register (from last frame)
Joy2Raw     DW

Joy1Press   DW      ; Contains only pressed buttons (not held down)
Joy2Press   DW

Joy1Held    DW      ; Contains only buttons that are Held
Joy2Held    DW

.ENDE

Alright, that's the variables. JoyRaw will act as a log of the raw data
received from reading the joypad registers. JoyPress will hold the buttons
that only been pressed for 1 frame. JoyHeld will hold data for the buttons
that have been pressed continously for > 1 frame. One example of the effects
you can do with button holds is running, such as in Super Mario World. Once Y
is pressed, Mario will accelerate as long Y is held until he reaches max speed.
Once Y is released, he slows down again. ta da

.ENUM is an easy way to map names to addresses. Joy1 is a word in size (DW),
so WLA just mapped Joy1 to $0000, and Joy2 to $0002 (leaving $0000 and $0001
for Joy1, a word). The other variables are mapped in the same way. If you
wanted to do it manually, you could .EQU (.DEFINE) xxxx $0000, but I personally
like this method because it automatically skips 1 or 2 addresses if it's a byte
or word..

Now, let's get on to reading the controllers, shall we? Onto some registers.

Register $4200: Counter Enable (1b/W)

n-vh---j        n: NMI enable                   v: vertical counter enable
                h: horizontal enable register   j: joypad enable

Register $4212: Status Register (1b/RW)
vh-----j        v:  0 = Not in VBlank state.
                    1 = In VBlank state.
                h:  0 = Not in HBlank state.
                    1 = In HBlank state.
                j:  0 = Joypad not ready.
                    1 = Joypad ready.

We just check bit 0 here to see if the joypad is ready to be read from. If the bit
is set, the joypads are NOT ready to be read from.

Register $4218: Joypad #1 status register (Low Byte) (1b/R)

axlriiii        a: A button
                x: X button
                l: L
                r: R
                i: Identification code

The button bits are set when the buttons are pressed. Also, the first 4 bits (i)
identify the type of controller connected. 0000 is the ID for a standard snes controller.
If these bits output anything else, there is something else plugged in or corrupt data. I'm
not going to check these in the routine because it's kind of pointless for homebrew. You either
plug in the normal controller or the program won't work.. I mean DUH. More important for commercial
games to check that...

Register $4219: Joypad #1 status register (High Byte) (1b/R)

bystudlr
                b: B button                u: Up
                y: Y button                d: Down
                s: Select                  l: Left
                t: Start                   r: Right

Quick Note: $4218 can be read with a 16 bit A/X/Y and both $4218 and $4219 will be read
at the same time. I think you can read or write to an address like that. But remember that
some registers require writing twice, one byte at a time.

Register $421A-$421F - Same as $4218-$4219 but for joypads 2-4.

Registers $4016-$4017: Old-style joypad registers (2*1b/RW)

$4016 - Player 1 Joypad
$4017 - Player 2 Joypad


So here's what's going to happen. When we enable NMI we'll also enable reading
of the joypads. That will be done through $4200. We'll also write a 0 to $4016
to have the ability of reading it to check if the pads are connected. After that
it's just a matter of jumping to the input routine during VBlank.

Full source available in download.

; Input Cheat Sheet
; $4218
; $80 = A
; $40 = X
; $20 = L
; $10 = R
; 
; $4219:
; $80 = B
; $40 = Y
; $20 = Select
; $10 = Start
; $08 = Up
; $04 = Down
; $02 = Left
; $01 = Right

; Let's define it to make it easier..
	
; $4218
.EQU Button_A		$80
.EQU Button_X		$40
.EQU Button_L		$20
.EQU Button_R		$10
; $4219
.EQU Button_B		$80
.EQU Button_Y		$40
.EQU Button_Select	$20
.EQU Button_Start	$10
.EQU Button_Up		$08
.EQU Button_Down	$04
.EQU Button_Left	$02
.EQU Button_Right	$01

    ; ....
    ; ..
    ; During initialization..
    stz $4016   ; Write a byte of nothing to $4016. You know why I did that?
    
    ;.. almost ready to enter main loop..
    lda #$81
    sta $4200   ; Enable NMI and auto-joypad read
    
Gameloop:
    WAI
    ;...
    ;.
    ;....
    ; react to input here..
    jmp Gameloop
    
VBlank:
    ;...
    ;..
    ;..
    ;.
    jsr Joypad
    ;.
    ;..
    rti
    
    ; Time for the real code  
Joypad:	
	lda $4212       ; auto-read joypad status
	and #$01        ; 
	bne Joypad     	; read is done when 0
	
	rep #$30        ; A/X/Y - 16 bit
	
	; Player 1
	ldx Joy1Raw		; load log of last frame's RAW read of $4218
	                ; the log will be 0 the first time read of course..
	lda $4218       ; Read current frame's RAW joypad data
	sta Joy1Raw     ; save it for next frame.. (last frame log is still in X)
	txa             ; transfer last frame input from X -> A (it's still in X too)
	eor Joy1Raw     ; Xor last frame input with current frame input
	                ; shows the changes in input
	                ; buttons just pressed or just released become set.
	                ; Held or unactive buttons are 0
	and Joy1Raw     ; AND changes to current frame's input.
	                ; this ends up leaving you with the only the buttons that are pressed..
	                ; It's MAGIC!
	sta Joy1Press	; Store just pressed buttons
	txa             ; Transfer last frame input from X -> A again
    and Joy1Raw		; Find buttons that are still pressed (held)
    sta Joy1Held    ; by storing only buttons that are pressed both frames
    
    ; Player 2      ; Repeat :)
    ldx Joy2Raw
	lda $421A       ; Read Joypad2 Regs
	sta Joy2Raw
	txa
	eor Joy2Raw     ; Find  just triggered buttons
	and Joy2Raw
	sta Joy2Press
	txa
    and Joy2Raw     ; Find buttons that are still pressed (held)
    sta Joy2Held
    
    ; Joypads standard (ie not a mouse or superscope..) and connected?
    sep #$20
    ldx #$0000          ; we'll clear recorded input if pad is invalid
    
    lda $4016           ; Pad 1 - now we read this (after we stored a 0 to it earlier)
    bne _check2         ; $4016 returns 0 if not connected, 1 if connected - branch if not 0
    stx Joy1Raw         ; otherwise clear all recorded input.. it's not valid..
    stx Joy1Press
    stx Joy1Held

_check2:    
    lda $4017           ; Pad 2
    bne _done           ; 0=not connected,
    stx Joy2Raw
    stx Joy2Press
    stx Joy2Held

_done:
    RTS
I'll upload source featuring input very soon..