Super NES Programming/Joypad Input
< Super NES ProgrammingJoypads are the SNES' means of input from the user. There can be up to four connected to the system, and there's support for special controllers, too (mouse, Super Scope, etc).
NOTE: This tutorial is a work-in-progress. I'm still relatively new to the SNES, so please feel free to correct any errors in this document.
Joypad Registers
To start off, we'll list the registers that we're going to use:
Size | Address | Description |
Byte | $4200 | Counter Enable |
Byte | $4212 | Status Register |
Word | $4218 | Joypad #1 Status |
Word | $421a | Joypad #2 Status |
Word | $421c | Joypad #3 Status |
Word | $421e | Joypad #4 Status |
Byte | $4016 | Joypad #1 Old-Style Status |
Byte | $4017 | Joypad #2 Old-Style Status |
Now, let's look at them in a bit more depth:
$4200 - Counter Enable n-vh---j
This register is most likely a bit familiar to you. If you've done any prior SNES coding, you'll recognize that you've probably used this register to enable a VSync interrupt. For joypad input, we must make sure bit 0 ("j") is set. This tells the SNES that we will be polling the other joypad registers.
What are the n-vh---j bits? Yes you say it's "most likely familliar" but for a layman like me who's JUST LEARNING SNES ASM language.I need to know what EVERY BIT of memory location does. So that I can figure out how to make it work. I'm just starting and I can't figure out, for the life of me, how to just do the SIMPLE TASK of reading the joypad. I came to this site looking for some help on telling me what everything does, from the first bit, to the last bit in all of SNES memory space, but I find that instead this site already ASSUMES that the reader knows most of this stuff. And yet I can't find any other site that is any better. They ALL assume you have SOME experience in this field of work (writing SNES ASM programs). So if you (the writer of this wiki article) could be so kind, please state what each bit does, by filling in the following table.
The n bit is: The v bit is: The h bit is: The j bit is the joypad polling bit.
$4212 - SNES Status Register vh-----j
This register is used to see if certain data is ready to be polled from the SNES. In this case, we only care about bit 0 ("j"). If we poll $4212 and bit 0 is set, then we know that the other SNES joypad registers will contain relevant data. It's usually not so bad if this step is left out, though. In the algorithm I'll be showing later, this check is skipped, but this explanation still exists for completeness.
$4218/9 through $421e/f - Joypad Status Registers hi:bystudlr lo:axlriiii
These are 16-bit registers that return the button and/or type states for each joypad connected to the SNES. $4218 and $4219 contain joypad 1's data, and joypad 2, 3, and 4 follow. The bits are laid out like this:
Bit(s) | Description |
$4219/b/d/f | (hi) |
b | B Button |
y | Y Button |
s | Select Button |
t | Start Button |
u | Up D-Pad Button |
d | Down D-Pad Button |
l | Left D-Pad Button |
r | Right D-Pad Button |
$4218/a/c/e | (lo) |
a | A Button |
x | X Button |
l | L Button |
r | R Button |
iiii | Controller Type ID |
Most of these are quite self-explanatory. If a corresponding button's bit is set, then that button is pressed. The only semi-confusing part of this is the mysterious "iiii" bits - these determine which kind of controller is connected to the port. Basically, if they read 0000, then it's a standard SNES controller. Otherwise, it's a custom controller type or corrupted data.
$4016 and $4017 - Joypad 1 and 2 Old-Style Status
For these, you'll notice I left out the specific bits of each register. Basically, these work just like reading states from NES. Because of this, I think it's redundant to include that information here, except that bit 0 of $4200 must be clear to do use them this way. These registers can still be useful, though. If you write 0 to $4016, then these two registers can be used to check if joypads 1 and 2 are connected. After writing the 0 (and you only need to write to $4016, not both), reading from the registers will return 0 if not connected, and something else if connected.