libdragon
Modules | Files | Data Structures | Functions
Controller Subsystem

Controller and accessory interface. More...

Modules

 Mempak Filesystem Routines
 Managed mempak interface.
 
 Transfer Pak interface
 Transfer Pak interface.
 

Files

file  controller.c
 Controller Subsystem.
 
file  controller.h
 Controller Subsystem.
 

Data Structures

struct  _SI_condat
 SI Nintendo 64 controller data. More...
 
struct  _SI_condat_gc
 SI GameCube controller data. More...
 
struct  SI_origdat_gc
 SI GameCube controller origin data. More...
 
struct  SI_controllers_state_t
 SI controller data for all controller ports. More...
 
struct  SI_controllers_origin_t
 SI GameCube controller origin data for all controller ports. More...
 
union  _SI_condat.__unnamed6__
 
struct  _SI_condat.__unnamed6__.__unnamed8__
 
struct  _SI_condat.__unnamed6__.__unnamed10__
 
union  _SI_condat_gc.__unnamed12__
 
struct  _SI_condat_gc.__unnamed12__.__unnamed14__
 
struct  _SI_condat_gc.__unnamed12__.__unnamed16__
 

Functions

void controller_init (void)
 Initialize the controller subsystem. More...
 
void controller_read (struct controller_data *output)
 Read the controller button status for all controllers. More...
 
void controller_read_gc (struct controller_data *outdata, const uint8_t rumble[4])
 Read the controller button status for all controllers, GC version. More...
 
void controller_read_gc_origin (struct controller_origin_data *outdata)
 Read the controller origin status for all controllers, GC version. More...
 
void controller_scan (void)
 Fetch the current controller state. More...
 
struct controller_data get_keys_down (void)
 Get keys that were pressed since the last inspection. More...
 
struct controller_data get_keys_up (void)
 Get keys that were released since the last inspection. More...
 
struct controller_data get_keys_held (void)
 Get keys that were held since the last inspection. More...
 
struct controller_data get_keys_pressed (void)
 Get keys that are currently pressed, regardless of previous state. More...
 
int get_dpad_direction (int controller)
 Return the DPAD calculated direction. More...
 
void execute_raw_command (int controller, int command, int bytesout, int bytesin, unsigned char *out, unsigned char *in)
 Execute a raw PIF command. More...
 
int get_controllers_present (void)
 Return a bitmask representing which controllers are present. More...
 
int get_accessories_present (struct controller_data *out)
 Return a bitmask specifying which controllers have recognized accessories. More...
 
int read_mempak_address (int controller, uint16_t address, uint8_t *data)
 Read a chunk of data from a mempak. More...
 
int write_mempak_address (int controller, uint16_t address, uint8_t *data)
 Write a chunk of data to a mempak. More...
 
int identify_accessory (int controller)
 Identify the accessory connected to a controller. More...
 
void rumble_start (int controller)
 Turn rumble on for a particular controller. More...
 
void rumble_stop (int controller)
 Turn rumble off for a particular controller. More...
 

Bitmasks for controller status

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.
 

Accessory ID Values

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.
 

SI Error Values

#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.
 

Detailed Description

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 Mempak Filesystem Routines handles reading and writing from the mempak in a way compatible with official games.


Data Structure Documentation

◆ _SI_condat

struct _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.__unnamed6__ __unnamed__

◆ _SI_condat_gc

struct _SI_condat_gc

SI GameCube controller data.

Data structure for Joybus response to 0x40 (Read GC controller state) command.

Data Fields
union _SI_condat_gc.__unnamed12__ __unnamed__

◆ SI_origdat_gc

struct 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.__unnamed6__

union _SI_condat.__unnamed6__
Data Fields
struct _SI_condat.__unnamed6__.__unnamed8__ __unnamed__
struct _SI_condat.__unnamed6__.__unnamed10__ __unnamed__

◆ _SI_condat.__unnamed6__.__unnamed8__

struct _SI_condat.__unnamed6__.__unnamed8__
Data Fields
unsigned int data: 32 32-bit data sent to or returned from SI

◆ _SI_condat.__unnamed6__.__unnamed10__

struct _SI_condat.__unnamed6__.__unnamed10__
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 X button.
signed y: 8 State of the Y button.

◆ _SI_condat_gc.__unnamed12__

union _SI_condat_gc.__unnamed12__

◆ _SI_condat_gc.__unnamed12__.__unnamed14__

struct _SI_condat_gc.__unnamed12__.__unnamed14__
Data Fields
uint64_t data 64-bit data sent to or returned from SI

◆ _SI_condat_gc.__unnamed12__.__unnamed16__

struct _SI_condat_gc.__unnamed12__.__unnamed16__
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

Function Documentation

◆ controller_init()

void controller_init ( void  )

Initialize the controller subsystem.

After initialization, the controllers will be scanned automatically in background one time per frame. You can access the last scanned status using get_keys_down, get_keys_up, get_keys_held get_keys_pressed, and get_dpad_direction.

◆ 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]outputStructure 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]outdataStructure to place the returned controller button status
[in]rumbleSet 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]outdataStructure 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]controllerThe 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]controllerThe controller (0-3) to send the command to
[in]commandThe command byte to send
[in]bytesoutThe number of parameter bytes the command requires
[in]bytesinThe number of result bytes expected
[in]outThe parameter bytes to send with the command
[out]inThe result bytes returned by the operation

◆ get_controllers_present()

int get_controllers_present ( void  )

Return a bitmask representing which controllers are present.

Queries the controller interface and returns a bitmask specifying which controllers are present. See CONTROLLER_1_INSERTED, CONTROLLER_2_INSERTED, CONTROLLER_3_INSERTED and CONTROLLER_4_INSERTED.

Returns
A bitmask representing controllers present

◆ get_accessories_present()

int get_accessories_present ( struct controller_data *  out)

Return a bitmask specifying which controllers have recognized accessories.

Queries the controller interface and returns a bitmask specifying which controllers have recognized accessories present. See CONTROLLER_1_INSERTED, CONTROLLER_2_INSERTED, CONTROLLER_3_INSERTED and CONTROLLER_4_INSERTED.

Returns
A bitmask representing accessories recognized

◆ 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]controllerWhich controller to read the data from (0-3)
[in]addressA 32 byte aligned offset to read from on the mempak
[out]dataBuffer to place 32 bytes of data read from the mempak
Return values
0if reading was successful
-1if the controller was out of range
-2if there was no mempak present in the controller
-3if 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]controllerWhich controller to write the data to (0-3)
[in]addressA 32 byte aligned offset to write to on the mempak
[out]dataBuffer to source 32 bytes of data to write to the mempak
Return values
0if writing was successful
-1if the controller was out of range
-2if there was no mempak present in the controller
-3if 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]controllerThe controller (0-3) to identify accessories on
Return values
ACCESSORY_RUMBLEPAKThe accessory connected is a rumblepak
ACCESSORY_MEMPAKThe accessory connected is a mempak
ACCESSORY_TRANSFERPAKThe accessory connected is a transferpak
ACCESSORY_VRUThe accessory connected is a VRU
ACCESSORY_NONEThe accessory was not recognized

◆ rumble_start()

void rumble_start ( int  controller)

Turn rumble on for a particular controller.

Parameters
[in]controllerThe controller (0-3) who's rumblepak should activate

◆ rumble_stop()

void rumble_stop ( int  controller)

Turn rumble off for a particular controller.

Parameters
[in]controllerThe controller (0-3) who's rumblepak should deactivate