We will assume that it is a normal rectangle NES pad you want to read and not anything funky. To read to see if a key is down, you read $4016 (Pad 1) or $4017 (Pad 2) once per key. If the key is down, Bit #0 (from right) will be set (1). And with 1 and jump if Not Equal. Before you read anything, however, you need to reset the pad (strobe).
To strobe/reset the pad, we write a 1 then a 0 to $4016 or $4017 (for pad 2). This is done like so:
That's it! Onto actually reading the pad.
Order of Reads
On every read of $4016 or $4017, you get the status of a different key. The order of keys read is: Read # | Corresponding Key
So how 'bout we learn some about conditions and jumps before we do any more?
Conditions And Jumps
There are certain "conditions" that are set by most instructions, some, however, can only be set by a compare instruction which'll be discussed later. These conditions are Conditions
- - EQual - Zero
- - Not EQual - Not Zero
- - Less Than
- - Greater Than
- - Positive
- - Negative
- - Carry Clear
- - Carry Set
- - oVerflow Clear
- - oVerflow Set
These conditions are set by most instructions, including loads. All of these have a branch instruction. Put a 'B' in front of one of those abbreviations and you'll have your branch (Conditional Jump) instruction, examples:
; assume that there is a label called Loopto .
beq Loopto ; branch to Loopto if last compare was EQual or last instruction
; resulted in a zero.
bpl Loopto ; branch if Bit #7 (always counted from right->left) is set. bmi Loopto ; branch if Bit #7 is clear. </code>
I hope you get the idea. I believe that only the Not Equal and Equal conditions can be set by a non-compare instruction.
Incase you don't know, a label is just a name/word followed by a colon ':'. Examples:
<code class=block> Loopto: aslkdfj: Hello_a: </code>
I hope you get the idea. Just remember:Labels are FUN!
A Small Example of Reading Keys
Enough talk, here's the code:
lda #$01 ; |
sta $4016 ; lda #$00 ; - Setup Pad for reading.
sta $4016 ; _/
lda $4016 ; read for A key. and #1 ; check to see if down. bne WasDown ; branch if it was down. ; I'm not sure why it's a BNE for a bit AND, it just is, SO USE IT! :) lda $4016 ; read for B key. lda $4016 ; read for SELECT lda $4016 ; read START status and #1 ; see if down. bne StartDown ; branch if down. lda $4016 ; UP lda $4016 ; DOWN lda $4016 ; LEFT lda $4016 ; RIGHT jmp NothingDown ; the JMP instruction jumps no matter what.
StartDown: ; Do stuff if START is pressed.
WasDown: ; Do stuff if A is pressed.
NothingDown: ; Nothing was down </code>
Hope you didn't think that was too hard! :) Personally, I find the GBA easier (a little) to program, so for me, NES programs take a little more studying to figure out.
This Day In Review
First, I'd like to mention that you probably know about my GBA ASM series and maybe you also know about my x86 (DOS) ASM tutorial? Switching between 3 ASM languages DOES sometimes screw me up, so if you see a something rather wierd or any mistake feel free to let me know. Thank you.
Also, I know Key Press Detecting isn't exactly all that exciting by itself, but things WILL GET MORE INTERESTING! I promise. ;)
Happy coding :),
-Mike H a.k.a GbaGuy