Controller and accessory interface.
More...
|
void | controller_init (void) |
| Initialize the controller subsystem.
|
|
void | controller_read (struct controller_data *output) |
| Read the controller button status for all controllers.
|
|
void | controller_read_gc (struct controller_data *outdata, const uint8_t rumble[4]) |
| Read the controller button status for all controllers, GC version.
|
|
void | controller_read_gc_origin (struct controller_origin_data *outdata) |
| Read the controller origin status for all controllers, GC version.
|
|
void | controller_scan (void) |
| Fetch the current controller state.
|
|
struct controller_data | get_keys_down (void) |
| Get keys that were pressed since the last inspection.
|
|
struct controller_data | get_keys_up (void) |
| Get keys that were released since the last inspection.
|
|
struct controller_data | get_keys_held (void) |
| Get keys that were held since the last inspection.
|
|
struct controller_data | get_keys_pressed (void) |
| Get keys that are currently pressed, regardless of previous state.
|
|
int | get_dpad_direction (int controller) |
| Return the DPAD calculated direction.
|
|
void | execute_raw_command (int controller, int command, int bytesout, int bytesin, unsigned char *out, unsigned char *in) |
| Execute a raw PIF command.
|
|
int | get_controllers_present (void) |
| Return a bitmask representing which controllers are present.
|
|
int | get_accessories_present (struct controller_data *out) |
| Return a bitmask specifying which controllers have recognized accessories.
|
|
int | read_mempak_address (int controller, uint16_t address, uint8_t *data) |
| Read a chunk of data from a mempak.
|
|
int | write_mempak_address (int controller, uint16_t address, uint8_t *data) |
| Write a chunk of data to a mempak.
|
|
int | identify_accessory (int controller) |
| Identify the accessory connected to a controller.
|
|
void | rumble_start (int controller) |
| Turn rumble on for a particular controller.
|
|
void | rumble_stop (int controller) |
| Turn rumble off for a particular controller.
|
|
|
- See also
- get_controllers_present
-
get_accessories_present
|
#define | CONTROLLER_1_INSERTED 0xF000 |
| Controller 1 Inserted.
|
|
#define | CONTROLLER_2_INSERTED 0x0F00 |
| Controller 2 Inserted.
|
|
#define | CONTROLLER_3_INSERTED 0x00F0 |
| Controller 3 Inserted.
|
|
#define | CONTROLLER_4_INSERTED 0x000F |
| Controller 4 Inserted.
|
|
|
- See also
- identify_accessory
|
#define | ACCESSORY_NONE 0 |
| No accessory present.
|
|
#define | ACCESSORY_MEMPAK 1 |
| Mempak present.
|
|
#define | ACCESSORY_RUMBLEPAK 2 |
| Rumblepak present.
|
|
#define | ACCESSORY_VRU 3 |
| VRU present.
|
|
#define | ACCESSORY_TRANSFERPAK 4 |
| Transferpak present.
|
|
|
#define | ERROR_NONE 0x0 |
| No error occured.
|
|
#define | ERROR_BAD_COMMAND 0x1 |
| Command not recognized or malformed.
|
|
#define | ERROR_NOT_PRESENT 0x2 |
| Controller not present.
|
|
Controller and accessory interface.
The controller subsystem is in charge of communication with all controllers and accessories plugged into the N64 controller ports. The controller subsystem leverages the Joybus Subsystem to provide controller data and interface with accessories such as the Controller Pak, Rumble Pak, Transfer Pak, and the Voice-Recognition Unit.
Code wishing to communicate with a controller or an accessory should first call controller_init. The controller subsystem performs an automatic background scanning of all controllers, in an efficient way, saving the current status in a local cache. Alternatively, it is possible to execute direct, blocking controller I/O reads, though they might be quite slow.
To read the controller status from this cache, call controller_scan once per frame (or whenever you want to perform the reading), and then call get_keys_down, get_keys_up, get_keys_held and get_keys_pressed, that will return the status of all keys relative to the previous inspection. get_dpad_direction will return a number signifying the polar direction that the D-Pad is being pressed in.
To perform direct reads to the controllers, call controller_read. This will return a structure consisting of all button states on all controllers currently inserted. Note that this function takes about 10% of a frame's worth of time.
Controllers can be enumerated with get_controllers_present. Similarly, accessories can be enumerated with get_accessories_present and identify_accessory.
To enable or disable rumbling on a controller, use rumble_start and rumble_stop. These functions will turn rumble on and off at full speed respectively, so if different rumble effects are desired, consider using the Timer Subsystem for accurate timing.
A mempak attached to a controller can be treated in one of two ways: as a raw binary string, or as a formatted mempak with notes. The former allows storage of any data as long as it fits, in any format convenient to the coder, but destroys any non-homebrew data on the mempak. The latter is recommended as it is completely compatible with official N64 games, though it allows less data to be stored due to filesystem overhead. To read and write raw sectors, use read_mempak_address and write_mempak_address. The Controller Pak Filesystem Routines handles reading and writing from the mempak in a way compatible with official games.
◆ _SI_condat
SI Nintendo 64 controller data.
Data structure for Joybus response to 0x01
(Read N64 controller state) command.
Data Fields |
unsigned |
__pad0__: 16 |
Unused padding bits. |
unsigned |
err: 2 |
Status of the last command. |
unsigned |
__pad1__: 14 |
Unused padding bits. |
union _SI_condat.__unnamed20__ |
__unnamed__ |
|
◆ _SI_condat_gc
SI GameCube controller data.
Data structure for Joybus response to 0x40
(Read GC controller state) command.
◆ SI_origdat_gc
SI GameCube controller origin data.
Data structure for Joybus response to 0x41
(Read GC controller origin) command.
Data Fields |
struct SI_condat_gc |
data |
|
uint8_t |
deadzone0 |
|
uint8_t |
deadzone1 |
|
◆ SI_controllers_state_t
struct SI_controllers_state_t |
SI controller data for all controller ports.
When reading N64 controller state, only the c
member array will be populated. When reading GC controller state, only the gc
member array will be populated.
Data Fields |
struct SI_condat |
c[4] |
Array of N64 controller state for each controller port. |
struct SI_condat_gc |
gc[4] |
Array of GameCube controller state for each controller port. |
◆ SI_controllers_origin_t
struct SI_controllers_origin_t |
SI GameCube controller origin data for all controller ports.
Data Fields |
struct SI_origdat_gc |
gc[4] |
Array of GameCube controller origin data for each controller port. |
◆ _SI_condat.__unnamed20__
union _SI_condat.__unnamed20__ |
◆ _SI_condat.__unnamed20__.__unnamed22__
struct _SI_condat.__unnamed20__.__unnamed22__ |
Data Fields |
unsigned int |
data: 32 |
32-bit data sent to or returned from SI |
◆ _SI_condat.__unnamed20__.__unnamed24__
struct _SI_condat.__unnamed20__.__unnamed24__ |
Data Fields |
unsigned |
A: 1 |
State of the A button. |
unsigned |
B: 1 |
State of the B button. |
unsigned |
Z: 1 |
State of the Z button. |
unsigned |
start: 1 |
State of the start button. |
unsigned |
up: 1 |
State of the up button. |
unsigned |
down: 1 |
State of the down button. |
unsigned |
left: 1 |
State of the left button. |
unsigned |
right: 1 |
State of the right button. |
unsigned |
__pad0__: 2 |
Unused padding bits. |
unsigned |
L: 1 |
State of the L button. |
unsigned |
R: 1 |
State of the R button. |
unsigned |
C_up: 1 |
State of the C up button. |
unsigned |
C_down: 1 |
State of the C down button. |
unsigned |
C_left: 1 |
State of the C left button. |
unsigned |
C_right: 1 |
State of the C right button. |
signed |
x: 8 |
State of the analog stick (X axis) |
signed |
y: 8 |
State of the analog stick (Y axis) |
◆ _SI_condat_gc.__unnamed26__
union _SI_condat_gc.__unnamed26__ |
◆ _SI_condat_gc.__unnamed26__.__unnamed28__
struct _SI_condat_gc.__unnamed26__.__unnamed28__ |
Data Fields |
uint64_t |
data |
64-bit data sent to or returned from SI |
◆ _SI_condat_gc.__unnamed26__.__unnamed30__
struct _SI_condat_gc.__unnamed26__.__unnamed30__ |
Data Fields |
unsigned |
err: 2 |
|
unsigned |
origin_unchecked: 1 |
|
unsigned |
start: 1 |
|
unsigned |
y: 1 |
|
unsigned |
x: 1 |
|
unsigned |
b: 1 |
|
unsigned |
a: 1 |
|
unsigned |
unused2: 1 |
|
unsigned |
l: 1 |
|
unsigned |
r: 1 |
|
unsigned |
z: 1 |
|
unsigned |
up: 1 |
|
unsigned |
down: 1 |
|
unsigned |
right: 1 |
|
unsigned |
left: 1 |
|
unsigned |
stick_x: 8 |
|
unsigned |
stick_y: 8 |
|
unsigned |
cstick_x: 8 |
|
unsigned |
cstick_y: 8 |
|
unsigned |
analog_l: 8 |
|
unsigned |
analog_r: 8 |
|
◆ controller_init()
void controller_init |
( |
void |
| ) |
|
◆ controller_read()
void controller_read |
( |
struct controller_data * |
output | ) |
|
Read the controller button status for all controllers.
Read the controller button status immediately and return results to data.
- Note
- This function is slow: it blocks for about 10% of a frame time. To avoid this hit, use the managed functions (get_keys_down, etc.).
- Parameters
-
[out] | output | Structure to place the returned controller button status |
◆ controller_read_gc()
void controller_read_gc |
( |
struct controller_data * |
outdata, |
|
|
const uint8_t |
rumble[4] |
|
) |
| |
Read the controller button status for all controllers, GC version.
Read the controller button status immediately and return results to data.
- Parameters
-
[out] | outdata | Structure to place the returned controller button status |
[in] | rumble | Set to 1 to start rumble, 0 to stop it. |
◆ controller_read_gc_origin()
void controller_read_gc_origin |
( |
struct controller_origin_data * |
outdata | ) |
|
Read the controller origin status for all controllers, GC version.
This returns the values set on power up, or the values the user requested by reseting the controller by holding X-Y-start. Apps should use these as the center stick values. The meaning of the two deadzone values is unknown.
- Parameters
-
[out] | outdata | Structure to place the returned controller button status |
◆ controller_scan()
void controller_scan |
( |
void |
| ) |
|
Fetch the current controller state.
This function must be called once per frame, or any time we want to update the state of the controllers. After calling this function, you can use get_keys_down, get_keys_up, get_keys_held, get_keys_pressed and get_dpad_direction to inspect the controller state.
This function is very fast. In fact, controllers are read in background asynchronously under interrupt, so this function just synchronizes the internal state.
◆ get_keys_down()
struct controller_data get_keys_down |
( |
void |
| ) |
|
Get keys that were pressed since the last inspection.
Return keys pressed since last detection. This returns a standard SI_controllers_state_t struct identical to controller_read. However, buttons are only set if they were pressed down since the last read.
- Returns
- A structure representing which buttons were just pressed down
◆ get_keys_up()
struct controller_data get_keys_up |
( |
void |
| ) |
|
Get keys that were released since the last inspection.
Return keys released since last detection. This returns a standard SI_controllers_state_t struct identical to controller_read. However, buttons are only set if they were released since the last read.
- Returns
- A structure representing which buttons were just released
◆ get_keys_held()
struct controller_data get_keys_held |
( |
void |
| ) |
|
Get keys that were held since the last inspection.
Return keys held since last detection. This returns a standard SI_controllers_state_t struct identical to controller_read. However, buttons are only set if they were held since the last read.
- Returns
- A structure representing which buttons were held
◆ get_keys_pressed()
struct controller_data get_keys_pressed |
( |
void |
| ) |
|
Get keys that are currently pressed, regardless of previous state.
This function works identically to controller_read except that it returns the cached data from the last background autoscan.
- Returns
- A structure representing which buttons were pressed
◆ get_dpad_direction()
int get_dpad_direction |
( |
int |
controller | ) |
|
Return the DPAD calculated direction.
Return the direction of the DPAD specified in controller. Follows standard polar coordinates, where 0 = 0, pi/4 = 1, pi/2 = 2, etc... Returns -1 when not pressed.
- Parameters
-
[in] | controller | The controller (0-3) to inspect |
- Returns
- A value 0-7 to represent which direction is held, or -1 when not pressed
◆ execute_raw_command()
void execute_raw_command |
( |
int |
controller, |
|
|
int |
command, |
|
|
int |
bytesout, |
|
|
int |
bytesin, |
|
|
unsigned char * |
out, |
|
|
unsigned char * |
in |
|
) |
| |
Execute a raw PIF command.
Send an arbitrary command to a controller and receive arbitrary data back
- Parameters
-
[in] | controller | The controller (0-3) to send the command to |
[in] | command | The command byte to send |
[in] | bytesout | The number of parameter bytes the command requires |
[in] | bytesin | The number of result bytes expected |
[in] | out | The parameter bytes to send with the command |
[out] | in | The result bytes returned by the operation |
◆ get_controllers_present()
int get_controllers_present |
( |
void |
| ) |
|
◆ get_accessories_present()
int get_accessories_present |
( |
struct controller_data * |
out | ) |
|
◆ read_mempak_address()
int read_mempak_address |
( |
int |
controller, |
|
|
uint16_t |
address, |
|
|
uint8_t * |
data |
|
) |
| |
Read a chunk of data from a mempak.
Given a controller and an address, read 32 bytes from a mempak and return them in data.
- Parameters
-
[in] | controller | Which controller to read the data from (0-3) |
[in] | address | A 32 byte aligned offset to read from on the mempak |
[out] | data | Buffer to place 32 bytes of data read from the mempak |
- Return values
-
0 | if reading was successful |
-1 | if the controller was out of range |
-2 | if there was no mempak present in the controller |
-3 | if the mempak returned invalid data |
◆ write_mempak_address()
int write_mempak_address |
( |
int |
controller, |
|
|
uint16_t |
address, |
|
|
uint8_t * |
data |
|
) |
| |
Write a chunk of data to a mempak.
Given a controller and an address, write 32 bytes to a mempak from data.
- Parameters
-
[in] | controller | Which controller to write the data to (0-3) |
[in] | address | A 32 byte aligned offset to write to on the mempak |
[out] | data | Buffer to source 32 bytes of data to write to the mempak |
- Return values
-
0 | if writing was successful |
-1 | if the controller was out of range |
-2 | if there was no mempak present in the controller |
-3 | if the mempak returned invalid data |
◆ identify_accessory()
int identify_accessory |
( |
int |
controller | ) |
|
Identify the accessory connected to a controller.
Given a controller, identify the particular accessory type inserted.
- Parameters
-
[in] | controller | The controller (0-3) to identify accessories on |
- Return values
-
◆ rumble_start()
void rumble_start |
( |
int |
controller | ) |
|
Turn rumble on for a particular controller.
- Parameters
-
[in] | controller | The controller (0-3) who's rumblepak should activate |
◆ rumble_stop()
void rumble_stop |
( |
int |
controller | ) |
|
Turn rumble off for a particular controller.
- Parameters
-
[in] | controller | The controller (0-3) who's rumblepak should deactivate |