1.2 Standard Controller
If you were to directly call N64 OS functions to perform Standard Controller processes, you would need to perform a number of transactions just to read the status of the Controller. However, with the NuSystem, these low-level processes are encapsulated, thus making reading of the Controller easy.
Below are the six representative Controller functions provided by the NuSystem:
nuContInit
Initializes the Controller and other SI devices
nuContDataGet
Gets the Controller data
nuContDataGetAll
Gets the data of all four Controllers
nuContDataGetEx
Expanded version of getting the Controller data
nuContDataGetExAll
Expanded version of getting the data of 4 Controllers
nuContQueryRead
Reads the Controller status
In most cases, these are the only functions you will need. The NuSystem supports many other Controller functions as well, so except for some special processes you will not need to make direct use of the N64 OS Controller functions.
1.2.1 Initializing the Controller
To perform Controller processes, the first thing you need to do is call the SI device initialization function nuContInit.
Function name: |
nuContInit |
Syntax: |
u8 nuContInit(void) |
Arguments: |
None |
Return Value: |
Bit pattern of the connected Controller |
Internally, the nuContInit function initializes the SI Manager (by calling the nuSiMgrInit function) and then initializes the Controller Manager, the Controller Pak Manager and the Rumble Pak Manager (by calling the nuContMgrInit function, nuContPakInit function and nuContRmbInit function).
The bit pattern of the connected Controller is stored in the return value from the nuContInit function. In order from the lowest bit, the return value corresponds to Controller 1, 2, 3 and 4.
The number of valid Controllers is set in the NuSystem global variable nuContNum when the Controller Manager is initialized, so you can reference this variable when necessary to check how many Controllers are connected.
Variable name: |
nuContNum |
Definition: |
u32 nuContNum |
Description: |
The number of connected Controllers |
The nuContInit function is useful because it calls the representative Managers (for the Controller, Controller Pak and Rumble Pak). However, it can also be wasteful because it may perform unnecessary processes. Initializing and registering the Rumble Pak Manager even for a game that does not support the Rumble Pak is one such an example.
In reality, nuContInit is a function for beginning N64 programmers, and once you have gained an understanding of the operation of each Manager, you should create your own initialization routines based on the source of the function.
1.2.2 Reading the Controller Data
Once you have started up the Controller Manager, the Controller data is read in every other frame and stored in an internal buffer of NuSystem. The contents of this internal buffer can be read out to the user area by calling such a function as nuContDataGet.
If you want to read out the status of one Controller, call the nuContDataGet function. If you want to read out the status of all Controllers, call the nuContDataGetAll function.
Function name: |
nuContDataGet |
Syntax: |
void nuContDataGet(OSContPad *contpad, u32 cont_no) |
Arguments: |
contpad |
Controller data structure |
|
cont_no |
The number of the controller to read |
Return Value: |
None |
Function name: |
nuContDataGetAll |
Syntax: |
void nuContDataGetAll(OSContPad *contpad) |
Arguments: |
contpad |
Controller data structure |
Return Value: |
None |
typedef struct
{
u16 button;
s8 stick_x;
s8 stick_y;
u8 errno;
} OSContPad;
|
button |
Bit pattern representing whether button is ON or OFF |
|
|
Check by doing a bitwise AND with the constant, CONT_A etc.
(see ) |
|
stick_x |
Horizontal tilt of the Control stick (-128 - 127)*1 |
|
stick_y |
Vertical tilt of the Control stick (-128 ~ 127)*1 |
|
errno |
Error number |
| *1(Note) Since the Controllers vary, the upper-limit value that can be input is not the same. To deal with this variation, please write your programs with the following values for the actual range of use: |
|
Horizontal direction (X axis) |
-61-61 |
|
Vertical direction (Y axis) |
-63-63 |
|
X-axis diagonal |
-45-45 |
|
Y-axis diagonal |
-47-47 |
Depending on the game, you may want to get trigger data like whether OFF has changed to ON, rather than about whether a button is being pressed at the time. The NuSystem defines the NUContData structure, which is the OSContPad structure with added trigger data. You can get trigger data by using the nuContDataGetEx function, which is the expanded version of the nuContDataGet function. To get data from all Controllers, use the nuContDataExALL function.
Function name: |
nuContDataGetEx |
Syntax: |
void nuContDataGetEx(NUContData *contdata, u32 padno) |
Arguments: |
contdata |
Pointer for storing the Controller data |
|
padno |
The pad number |
Return Value: |
None |
Function name: |
nuContDataGetExAll |
Syntax: |
void nuContDataGetExAll(NUContData *contdata) |
Arguments: |
contdata |
Pointer for storing the Controller data |
Return Value: |
None |
typedef struct
{
u16 button;
s8 stick_x;
s8 stick_y;
u8 errno;
u16 trigger;
} NUContData;
|
button |
Bit pattern representing whether button is ON or OFF
|
|
|
Check by doing a bitwise AND with the constant, CONT_A etc.
(see ) |
|
stick_x |
Horizontal tilt of the Control stick *2 |
|
stick_y |
Vertical tilt of the Control stick *2 |
|
errno |
Error number |
|
trigger |
Bit pattern of the trigger data (the same order of "button") |
| *2(Note) Since the Controllers vary, the upper-limit value that can be input is not the same. To deal with this variation, please write your programs with the following values for the real range of use:
|
|
Horizontal direction (X axis) |
-61-61 |
|
Vertical direction (Y axis) |
-63-63 |
|
X-axis diagonal |
-45-45 |
|
Y-axis diagonal |
-47-47 |
The trigger data is calculated with a logical operation involving the contents of the "contdata" argument passed to the function, and the Controller data read at that time, so be sure to make contdata a static variable.
1.2.3 Reading the Controller Status
When the Controller Manager is initialized, the Controller status (i.e., whether or not there is a Controller and the type) is stored in the NuSystem global variable nuContStatus.
If you want to read out the current Controller status, call the nuContQueryRead function. This result is also stored in nuContStatus, but it takes about 2 milliseconds to get the status this way.
Variable name: |
nuContStatus |
Definition: |
OSContStatus nuContStatus[NU_CONT_MAXCONTROLLERS] |
Function name: |
nuContQueryRead |
Syntax: |
void nuContQueryRead(void) |
Arguments: |
None |
Return Value: |
None |
typedef struct
{
u16 type;
u8 status;
u8 errno;
} OSContStatus;
|
type |
The type of the Controller connected to the port |
|
|
This type and the constant CONT_JOYPORT etc. (see ) are
bit ORed for the check. |
|
status |
Controller status |
|
|
For example, if the Controller Pak is connected, the CONT_CARD_ON
bit is ON |
|
errno |
Error number |
To verify that the Standard Controller is inserted, mask with CONT_TYPE_MASK and then check whether equal to CONT_TYPE_NORMAL. If the Controller is not connected to the port, then the CONT_NO_RESPONSE_ERROR bit is set in errno.