Use the SNES/NES controllers: Difference between revisions
mNo edit summary |
|||
| (5 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
== NES and SNES controllers == | == NES and SNES controllers == | ||
The F256 machines can use these controllers provided they are equipped with an optional | The F256 machines can use these controllers provided they are equipped with an optional FNX4N4S breakout adapter (website purchase link no longer active). | ||
The official gamepads of yesteryear work without issue with this and are plentiful in the used market. | The official gamepads of yesteryear work without issue with this and are plentiful in the used market. | ||
| Line 7: | Line 7: | ||
Super famicom gamepads work very well as substitute for regular SNES gamepads. | Super famicom gamepads work very well as substitute for regular SNES gamepads. | ||
If your FNX4N4S adapter box is not working reliably, go check how to resolve a potential issue in the [[Troubleshooting|Troubleshoot]] page. | |||
[[File:Full complement of gamepads.png|thumb|A fully populated FNX4N4S for the F256K2]] | |||
=== Registers === | === Registers === | ||
| Line 314: | Line 317: | ||
|R | |R | ||
|} | |} | ||
Notes: | |||
* L refers to the left shoulder button and R refers to the right shoulder button. | |||
* Buttons are active low! Bits are 1 when unpressed, 0 when pressed. | |||
=== Usage === | === Usage === | ||
| Line 321: | Line 327: | ||
<pre> | <pre> | ||
POKE(PAD_CTRL, 0b10000001); //trigger, nes mode, enabled | POKE(PAD_CTRL, 0b10000001); //trigger, nes mode, enabled | ||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
POKE(PAD_CTRL, 0b00000001); //clear trigger | POKE(PAD_CTRL, 0b00000001); //clear trigger | ||
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | ||
| Line 331: | Line 339: | ||
<pre> | <pre> | ||
POKE(PAD_CTRL, 0b10000101); //trigger, snes mode, enabled | POKE(PAD_CTRL, 0b10000101); //trigger, snes mode, enabled | ||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
POKE(PAD_CTRL, 0b00000101); //clear trigger | POKE(PAD_CTRL, 0b00000101); //clear trigger | ||
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | ||
| Line 342: | Line 352: | ||
//NES section | //NES section | ||
POKE(PAD_CTRL, 0b10000001); //trigger, nes mode, enabled | POKE(PAD_CTRL, 0b10000001); //trigger, nes mode, enabled | ||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
POKE(PAD_CTRL, 0b00000001); //clear trigger | POKE(PAD_CTRL, 0b00000001); //clear trigger | ||
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | ||
| Line 350: | Line 362: | ||
//SNES section | //SNES section | ||
POKE(PAD_CTRL, 0b10000101); //trigger, snes mode, enabled | POKE(PAD_CTRL, 0b10000101); //trigger, snes mode, enabled | ||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
ASM("NOP"); //a necessary delay with the 2x speed core | |||
POKE(PAD_CTRL, 0b00000101); //clear trigger | POKE(PAD_CTRL, 0b00000101); //clear trigger | ||
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared | ||
Latest revision as of 00:37, 3 February 2026
NES and SNES controllers
The F256 machines can use these controllers provided they are equipped with an optional FNX4N4S breakout adapter (website purchase link no longer active).
The official gamepads of yesteryear work without issue with this and are plentiful in the used market.
Third party modern recreations are sometimes flaky or not working at all. Share you discoveries in the discord!
Super famicom gamepads work very well as substitute for regular SNES gamepads.
If your FNX4N4S adapter box is not working reliably, go check how to resolve a potential issue in the Troubleshoot page.

Registers
| Register Name | R/W | Address | NES/SNES | Description |
|---|---|---|---|---|
| PAD_CTRL | W | 0xD880 | both | Used to trigger a reading and setting the NES/SNES mode |
| PAD_STAT | R | 0xD880 | both | Used to verify if the triggered polling of gamepad state is done yet |
| PAD0 | R | 0xD884 | both | Buttons statuses: if cleared, they are pressed. If set, they are unpressed. |
| PAD0_S | R | 0xD885 | SNES | Same deal; unused by NES. Consult button table below |
| PAD1 | R | 0xD886 | both | Buttons statuses: if cleared, they are pressed. If set, they are unpressed. |
| PAD1_S | R | 0xD887 | SNES | Same deal; unused by NES. Consult button table below |
| PAD2 | R | 0xD888 | both | Buttons statuses: if cleared, they are pressed. If set, they are unpressed. |
| PAD2_S | R | 0xD889 | SNES | Same deal; unused by NES. Consult button table below |
| PAD3 | R | 0xD88A | both | Buttons statuses: if cleared, they are pressed. If set, they are unpressed. |
| PAD3_S | R | 0xD88B | SNES | Same deal; unused by NES. Consult button table below |
Control register
| Register Name | R/W | Address | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
|---|---|---|---|---|---|---|---|---|---|---|
| PAD_CTRL | W | 0xD880 | NES_TRIG | - | - | - | - | MODE | - | EN |
| PAD_STAT | R | 0xD880 | NES_TRIG | DONE | - | - | - | MODE | - | EN |
Control register bit states:
| Bit Name | If set to 1 | If cleared to 0 |
|---|---|---|
| NES_TRIG | Launches the polling of the states of all buttons | Stops polling the states of all buttons |
| DONE | The states of the buttons are ready to be read | The states of the buttons are not ready |
| MODE | SNES data will be used to populate the PAD registers | NES data will be used to populate the PAD registers |
| EN | Enables the gamepads | Disables the gamepads |
Button table
| MODE | NES/SNES | Address | Pad | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | NES | 0xD884 | 0 | A | B | Select | Start | Up | Down | Left | Right |
| 0 | NES | 0xD886 | 1 | A | B | Select | Start | Up | Down | Left | Right |
| 0 | NES | 0xD888 | 2 | A | B | Select | Start | Up | Down | Left | Right |
| 0 | NES | 0xD88A | 3 | A | B | Select | Start | Up | Down | Left | Right |
| 1 | SNES | 0xD884 | 0 | B | Y | Select | Start | Up | Down | Left | Right |
| 1 | SNES | 0xD885 | 0 | A | X | L | R | ||||
| 1 | SNES | 0xD886 | 1 | B | Y | Select | Start | Up | Down | Left | Right |
| 1 | SNES | 0xD887 | 1 | A | X | L | R | ||||
| 1 | SNES | 0xD888 | 2 | B | Y | Select | Start | Up | Down | Left | Right |
| 1 | SNES | 0xD889 | 2 | A | X | L | R | ||||
| 1 | SNES | 0xD88A | 3 | B | Y | Select | Start | Up | Down | Left | Right |
| 1 | SNES | 0xD88B | 3 | A | X | L | R |
Notes:
- L refers to the left shoulder button and R refers to the right shoulder button.
- Buttons are active low! Bits are 1 when unpressed, 0 when pressed.
Usage
Example 1: polling a NES controller in PAD0 position and checking if A is pressed:
POKE(PAD_CTRL, 0b10000001); //trigger, nes mode, enabled
ASM("NOP"); //a necessary delay with the 2x speed core
ASM("NOP"); //a necessary delay with the 2x speed core
POKE(PAD_CTRL, 0b00000001); //clear trigger
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared
;
if((PEEK(PAD0) & 0x80) == 0) reactToAPressed();
Example 2: polling a SNES controller in PAD2 position and checking if X is pressed:
POKE(PAD_CTRL, 0b10000101); //trigger, snes mode, enabled
ASM("NOP"); //a necessary delay with the 2x speed core
ASM("NOP"); //a necessary delay with the 2x speed core
POKE(PAD_CTRL, 0b00000101); //clear trigger
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared
;
if((PEEK(PAD2_S) & 0x04) == 0) reactToXPressed();
Example 3: polling both types of controller in rapid succession (allows the usage of all 8 controllers!)
//NES section
POKE(PAD_CTRL, 0b10000001); //trigger, nes mode, enabled
ASM("NOP"); //a necessary delay with the 2x speed core
ASM("NOP"); //a necessary delay with the 2x speed core
POKE(PAD_CTRL, 0b00000001); //clear trigger
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared
;
//section where reactions are made to the various NES presses
//SNES section
POKE(PAD_CTRL, 0b10000101); //trigger, snes mode, enabled
ASM("NOP"); //a necessary delay with the 2x speed core
ASM("NOP"); //a necessary delay with the 2x speed core
POKE(PAD_CTRL, 0b00000101); //clear trigger
while((PEEK(PAD_STAT) & 0x40) == 0) //loop while this bit is cleared
;
//section where reactions are made to the various SNES presses
Source code example in C:
Check out this simple example displaying the statuses of all 4 NES pads on screen, using hex: https://github.com/Mu0n/F256KsimpleCdoodles/tree/main/NES/src