Dissolve gPortInfo

This commit is contained in:
Arceveti
2023-07-30 14:55:20 -07:00
parent 338eee167c
commit f93d47b7ba
8 changed files with 101 additions and 100 deletions

View File

@@ -316,7 +316,7 @@ typedef union {
} raw; /*0x08*/
} GCNInputData; /*0x08*/
// -- Virtual Controller (OSContPadEx) buttons --
// -- Virtual Controller buttons (used by OSContPadEx) --
typedef union {
struct PACKED {
@@ -340,8 +340,8 @@ typedef union {
* Structure for controllers
*/
typedef struct {
/*0x00*/ u16 type; /* Controller Type */
typedef struct { //! TODO: Accessory type.
/*0x00*/ u16 type; /* Controller Type (SI identifier, byteswapped) */
/*0x02*/ u8 status; /* Controller status */
/*0x03*/ u8 error; /* Error */
} OSContStatus; /*0x04*/
@@ -365,17 +365,19 @@ typedef struct PACKED {
typedef struct {
/*0x00*/ OSContButtons button; /* Button data */
/*0x02*/ OSContButtons lockedButton; /* Button data to ignore */
/*0x04*/ Analog_s8 stick; /* -80 <= stick <= 80 */
/*0x06*/ Analog_s8 c_stick; /* -80 <= c_stick <= 80 */
/*0x08*/ Analog_u8 trig; /* 0 <= trig <= 255 */
/*0x0A*/ OSContOrigins origins; /* GCN analog origins */
/*0x12*/ union { /* Extra bits not set by controller buttons */
/*0x04*/ OSContButtons statPollButton; /* Previous frame's inputs when status polling. */
/*0x06*/ Analog_s8 stick; /* -80 <= stick <= 80 */
/*0x08*/ Analog_s8 c_stick; /* -80 <= c_stick <= 80 */
/*0x0A*/ Analog_u8 trig; /* 0 <= trig <= 255 */
/*0x0C*/ OSContOrigins origins; /* GCN analog origins */
/*0x14*/ union { /* Extra bits not set by controller buttons */
N64Buttons n64;
GCNButtons gcn;
u16 raw;
} ex; /*0x02*/
/*0x14*/ u8 errno; /* Error number */
} OSContPadEx; /*0x15*/
/*0x16*/ u8 gcnRumble; /* Stored GCN rumble byte */
/*0x17*/ u8 errno; /* Error number */
} OSContPadEx; /*0x18*/
typedef struct {
/*0x00*/ void *address; /* Ram pad Address: 11 bits */

View File

@@ -455,7 +455,6 @@ void render_controllers_overlay(void) {
const s32 texW = 32;
const s32 texH = 32;
Texture* texture_controller = texture_controller_unknown;
OSPortInfo* portInfo = NULL;
char text_buffer[32] = "";
int port;
@@ -478,11 +477,9 @@ void render_controllers_overlay(void) {
// Draw the port icons:
for (port = 0; port < MAXCONTROLLERS; port++) {
portInfo = &gPortInfo[port];
// Loop through sControllerIcons to get the port's corresponding texture.
for (int i = 0; i < ARRAY_COUNT(sControllerIcons); i++) {
if (portInfo->type == sControllerIcons[i].type) {
if (gControllerStatuses[port].type == sControllerIcons[i].type) {
texture_controller = sControllerIcons[i].texture;
break;
}
@@ -531,10 +528,9 @@ void render_controllers_overlay(void) {
// Print the assigned port numbers.
for (port = 0; port < MAXCONTROLLERS; port++) {
portInfo = &gPortInfo[port];
if (portInfo->plugged && portInfo->playerNum) {
sprintf(text_buffer, "P%d", portInfo->playerNum);
// Print if a controller is plugged in and assigned to a player.
if ((gControllerStatuses[port].type != CONT_NONE) && (gControllerPlayerNumbers[port] != 0)) {
sprintf(text_buffer, "P%d", gControllerPlayerNumbers[port]);
drawSmallString(&dlHead, ((SCREEN_CENTER_X - (w * (MAXCONTROLLERS / 2))) + (w * port) + 8), (SCREEN_CENTER_Y + 16), text_buffer);
}
}

View File

@@ -22,6 +22,7 @@ struct Controller* const gPlayer4Controller = &gControllers[3];
// OS Controllers.
OSContStatus gControllerStatuses[MAXCONTROLLERS];
OSContPadEx gControllerPads[MAXCONTROLLERS];
u8 gControllerPlayerNumbers[MAXCONTROLLERS]; // 0 = not assigned to a player.
u8 gNumPlayers = 0; // The number of controllers currently assigned to a player.
u8 gControllerBits = 0b0000; // Which ports have a controller connected to them (low to high).
@@ -170,7 +171,7 @@ ALWAYS_INLINE _Bool check_button_pressed_combo(u16 buttonDown, u16 buttonPressed
* @param[out] controller The controller to link.
* @param[in ] port The port to get the data from.
*/
void assign_controller_data(struct Controller* controller, int port) {
void assign_controller_data_to_port(struct Controller* controller, int port) {
controller->statusData = &gControllerStatuses[port];
controller->controllerData = &gControllerPads[port];
controller->port = port;
@@ -181,7 +182,6 @@ void assign_controller_data(struct Controller* controller, int port) {
* Automatically assignins controller numbers based on port order.
*/
void assign_controllers_by_port_order(void) {
OSPortInfo* portInfo = NULL;
int port, cont = 0;
int lastUsedPort = -1;
@@ -192,13 +192,11 @@ void assign_controllers_by_port_order(void) {
break;
}
portInfo = &gPortInfo[port];
// Is a controller plugged in?
if (gControllerStatuses[port].type != CONT_NONE) {
gControllerPlayerNumbers[port] = (cont + 1);
// Is the controller plugged in?
if (portInfo->plugged) {
portInfo->playerNum = (cont + 1);
assign_controller_data(&gControllers[cont], port);
assign_controller_data_to_port(&gControllers[cont], port);
lastUsedPort = port;
@@ -215,18 +213,17 @@ void assign_controllers_by_port_order(void) {
* Assigns controllers based on assigned data from status polling.
*/
void assign_controllers_by_player_num(void) {
OSPortInfo* portInfo = NULL;
int port;
int lastUsedPort = -1;
// Loop over the 4 ports and link the controller structs to the appropriate status and pad.
// The game allows you to have a controller plugged into any port in order to play the game.
for (port = 0; port < MAXCONTROLLERS; port++) {
portInfo = &gPortInfo[port];
u8 playerNum = gControllerPlayerNumbers[port];
// Is controller plugged in and assigned to a player?
if (portInfo->plugged && portInfo->playerNum) {
assign_controller_data(&gControllers[portInfo->playerNum - 1], port);
// Is a controller plugged in and assigned to a player?
if ((gControllerStatuses[port].type != CONT_NONE) && (playerNum != 0)) {
assign_controller_data_to_port(&gControllers[playerNum - 1], port);
lastUsedPort = port;
}
@@ -282,12 +279,33 @@ static void poll_controller_statuses(OSMesg* mesg) {
release_rumble_pak_control();
}
/**
* @brief Disconnects/resets all controller data.
*/
void reset_all_controller_data(void) {
gNumPlayers = 0;
bzero(gControllers, sizeof(gControllers ));
bzero(gControllerStatuses, sizeof(gControllerStatuses ));
bzero(gControllerPads, sizeof(gControllerPads ));
bzero(gControllerPlayerNumbers, sizeof(gControllerPlayerNumbers));
// for (int port = 0; port < MAXCONTROLLERS; port++) {
// gControllerPads[port].statPollButton.raw = 0x0000;
// gControllerPads[port].gcnRumble = 0;
// }
cancel_rumble();
}
/**
* @brief Starts polling for new controllers and open the UI.
* @param[in] isBootMode Boolean. Only used when MAX_SUPPORTED_CONTROLLERS is 1. Triggers a separate mode where the UI is
* invisible and the controller with the first detected input (including analog sticks) becomes player 1.
*/
void start_controller_status_polling(_Bool isBootMode) {
reset_all_controller_data();
if (isBootMode) {
gContStatusPollingReadyForInput = TRUE;
}
@@ -295,13 +313,6 @@ void start_controller_status_polling(_Bool isBootMode) {
gContStatusPollingIsBootMode = isBootMode;
gContStatusPolling = TRUE;
gContStatusPollTimer = 0;
gNumPlayers = 0;
bzero(gPortInfo, sizeof(gPortInfo ));
bzero(gControllers, sizeof(gControllers ));
bzero(gControllerStatuses, sizeof(gControllerStatuses));
cancel_rumble();
}
/**
@@ -349,22 +360,21 @@ static _Bool detect_analog_stick_input(OSContPadEx* pad, const s8 deadzone) {
* @brief Assign player numbers to controllers based on player input.
*/
void read_controller_inputs_status_polling(void) {
OSPortInfo* portInfo = NULL;
u16 totalInput = 0x0;
// Read inputs from all four ports when status polling.
for (int port = 0; port < MAXCONTROLLERS; port++) {
portInfo = &gPortInfo[port];
OSContPadEx* pad = &gControllerPads[port];
if (portInfo->plugged) {
OSContPadEx* pad = &gControllerPads[port];
// Check whether a controller is plugged in to this port.
if (gControllerStatuses[port].type != CONT_NONE) {
u16 button = pad->button.raw;
totalInput |= button;
if (gContStatusPollingReadyForInput) {
// If a button is pressed on an unassigned controller, assign it the current player number.
if (
!portInfo->playerNum &&
(gControllerPlayerNumbers[port] == 0) &&
(
button ||
(
@@ -373,15 +383,15 @@ void read_controller_inputs_status_polling(void) {
) // Only check analog sticks in boot mode.
)
) {
portInfo->playerNum = ++gNumPlayers;
gControllerPlayerNumbers[port] = ++gNumPlayers;
}
#if (defined(ALLOW_STATUS_REPOLLING_COMBO) && (MAX_NUM_PLAYERS > 1))
u16 pressed = (~portInfo->statusPollButtons & button);
u16 pressed = (~pad->statPollButton.raw & button);
// If the combo is pressed, stop polling and assign the current controllers.
if (
!gContStatusPollingIsBootMode &&
portInfo->playerNum &&
(gControllerPlayerNumbers[port] != 0) &&
check_button_pressed_combo(button, pressed, TOGGLE_CONT_STATUS_POLLING_COMBO)
) {
gContStatusPollingReadyForInput = FALSE;
@@ -398,10 +408,10 @@ void read_controller_inputs_status_polling(void) {
return;
}
portInfo->statusPollButtons = button;
pad->statPollButton.raw = button;
}
} else {
portInfo->statusPollButtons = 0x0000;
pad->statPollButton.raw = 0x0000;
}
}

View File

@@ -33,6 +33,7 @@ extern struct Controller* const gPlayer4Controller;
// OS Controllers.
extern OSContStatus gControllerStatuses[MAXCONTROLLERS];
extern OSContPadEx gControllerPads[MAXCONTROLLERS];
extern u8 gControllerPlayerNumbers[MAXCONTROLLERS];
extern u8 gNumPlayers;
extern u8 gControllerBits;

View File

@@ -8,8 +8,6 @@
#include "input.h"
#include "rumble.h"
OSPortInfo gPortInfo[MAXCONTROLLERS] = { 0 };
void __osSiGetAccess(void);
void __osSiRelAccess(void);
@@ -104,10 +102,10 @@ s32 osStartRead_impl(OSMesgQueue* mq, u8 cmdID) {
(dst) += sizeof(src); \
}
#define WRITE_PIF_CMD_WITH_GCN_RUMBLE(dst, src) { \
(*(typeof(src)*)(dst)) = (src); \
(*(typeof(src)*)(dst)).send.rumble = portInfo->gcnRumble; \
(dst) += sizeof(src); \
#define WRITE_PIF_CMD_WITH_GCN_RUMBLE(dst, src) { \
(*(typeof(src)*)(dst)) = (src); \
(*(typeof(src)*)(dst)).send.rumble = pad->gcnRumble; \
(dst) += sizeof(src); \
}
/**
@@ -118,21 +116,22 @@ s32 osStartRead_impl(OSMesgQueue* mq, u8 cmdID) {
*/
static void __osPackRead_impl(u8 cmdID) {
u8* ptr = (u8*)__osContPifRam.ramarray;
OSPortInfo* portInfo = NULL;
OSContPadEx* pad = NULL;
int port;
bzero(__osContPifRam.ramarray, sizeof(__osContPifRam.ramarray));
__osContPifRam.pifstatus = PIF_STATUS_EXE;
for (port = 0; port < __osMaxControllers; port++) {
portInfo = &gPortInfo[port];
pad = &gControllerPads[port];
// Make sure this port has a controller plugged in, and if not status repolling, only poll assigned ports.
_Bool isEnabled = (portInfo->plugged && (gContStatusPolling || portInfo->playerNum));
_Bool isGCN = (portInfo->type & CONT_CONSOLE_GCN);
u16 type = gControllerStatuses[port].type;
_Bool isEnabled = ((type != CONT_NONE) && (gContStatusPolling || (gControllerPlayerNumbers[port] != 0)));
_Bool isGCN = (type & CONT_CONSOLE_GCN);
switch (cmdID) {
case CONT_CMD_READ_BUTTON:
case CONT_CMD_READ_BUTTON: // Instead of running these commands separately, run one or the other per port depending on the connected controller type.
case CONT_CMD_GCN_SHORT_POLL:
if (isEnabled) {
if (isGCN) {
@@ -434,8 +433,7 @@ void osContGetQueryEx(u8* bitpattern, OSContStatus* status) {
void __osContGetInitDataEx(u8* pattern, OSContStatus* status) {
u8* ptr = (u8*)__osContPifRam.ramarray;
__OSContRequestFormatAligned requestHeader;
OSPortInfo* portInfo = NULL;
u8 bits = 0x0;
u8 bits = 0b0000;
int port;
for (port = 0; port < __osMaxControllers; port++) {
@@ -443,19 +441,18 @@ void __osContGetInitDataEx(u8* pattern, OSContStatus* status) {
status->error = CHNL_ERR(requestHeader.fmt.size);
if (status->error == (CHNL_ERR_SUCCESS >> 4)) {
portInfo = &gPortInfo[port];
// Byteswap the SI identifier. This is done in vanilla libultra.
status->type = ((requestHeader.fmt.recv.type.l << 8) | requestHeader.fmt.recv.type.h);
// Check the type of controller device connected to the port.
// Some mupen cores seem to send back a controller type of CONT_TYPE_NULL (0xFFFF) if the core doesn't initialize the input plugin quickly enough,
// so check for that and set the input type to N64 controller if so.
portInfo->type = ((s16)status->type == (s16)CONT_TYPE_NULL) ? CONT_TYPE_NORMAL : status->type;
if ((s16)status->type == (s16)CONT_TYPE_NULL) {
status->type = CONT_TYPE_NORMAL;
}
// Set this port's status.
// Set this port's status byte.
status->status = requestHeader.fmt.recv.status.raw;
portInfo->plugged = TRUE;
bits |= (1 << port);
}
@@ -492,8 +489,9 @@ s32 __osMotorAccessEx(OSPfs* pfs, s32 motorState) {
return PFS_ERR_INVALID;
}
if (gPortInfo[channel].type & CONT_CONSOLE_GCN) { // GCN Controllers.
gPortInfo[channel].gcnRumble = motorState;
// Check whether the controller is a GCN controller.
if (gControllerStatuses[channel].type & CONT_CONSOLE_GCN) {
gControllerPads[channel].gcnRumble = motorState;
// Change the last command ID so that input poll command (which includes rumble) gets written again.
__osContLastCmd = PIF_CMD_END;
@@ -599,7 +597,8 @@ s32 osMotorInitEx(OSMesgQueue* mq, OSPfs* pfs, int channel) {
pfs->channel = channel;
pfs->activebank = ACCESSORY_ID_NULL;
if (!(gPortInfo[channel].type & CONT_CONSOLE_GCN)) {
// Make sure the controller is not a GCN controller.
if (!(gControllerStatuses[channel].type & CONT_CONSOLE_GCN)) {
// Write probe value (ensure Transfer Pak is turned off).
err = __osPfsSelectBank(pfs, ACCESSORY_ID_TRANSFER_OFF);
if (err == PFS_ERR_NEW_PACK) {

View File

@@ -656,15 +656,6 @@ typedef struct PACKED {
/*0x04*/ void (*packFunc)(void); // The function that writes to __osContPifRam.
} CommandPackFunc; /*0x08*/
typedef struct PACKED {
/*0x00*/ u16 type; // The SI identifier of the device plugged into this port.
/*0x02*/ u16 accessory; //! TODO: Accessory type in the controller plugged into in this port.
/*0x04*/ u16 statusPollButtons; // Input, only used when status polling to save the previous frame's inputs.
/*0x06*/ _Bool plugged; // Whether a controller is plugged in to this port.
/*0x07*/ u8 playerNum; // The player number. [0, 4]. 0 = not assigned to a player.
/*0x08*/ u8 gcnRumble; // Stored GCN Rumble byte.
} OSPortInfo; /*0x09*/
/////////////
// externs //
/////////////
@@ -675,6 +666,6 @@ extern u8 __osMaxControllers; // The last port to read controllers on.
extern u8 __osContLastCmd; // The ID of the last command that was executed.
// From HackerSM64:
extern OSPortInfo gPortInfo[MAXCONTROLLERS];
// extern OSPortInfo gPortInfo[MAXCONTROLLERS];
void __osContGetInitDataEx(u8* pattern, OSContStatus* status);

View File

@@ -231,7 +231,7 @@ u32 profiler_get_rdp_microseconds() {
void profiler_print_times() {
u32 microseconds[PROFILER_TIME_COUNT];
char text_buffer[196];
char text_buffer[256] = "";
update_fps_timer();
update_total_timer();
@@ -245,10 +245,11 @@ void profiler_print_times() {
#endif
#ifdef PUPPYPRINT_DEBUG
if (fDebug && sPPDebugPage == PUPPYPRINT_PAGE_PROFILER) {
if (fDebug && sPPDebugPage == PUPPYPRINT_PAGE_PROFILER)
#else
if (show_profiler) {
if (show_profiler)
#endif
{
for (int i = 0; i < PROFILER_TIME_COUNT; i++) {
if (i < PROFILER_TIME_TMEM) {
microseconds[i] = OS_CYCLES_TO_USEC(all_profiling_data[i].total / PROFILING_BUFFER_SIZE);
@@ -259,8 +260,8 @@ void profiler_print_times() {
// audio time is removed from the main thread profiling, so add it back here
u32 total_cpu = microseconds[PROFILER_TIME_TOTAL] + microseconds[PROFILER_TIME_AUDIO] * 2;
u32 total_rsp = microseconds[PROFILER_TIME_RSP_GFX] + microseconds[PROFILER_TIME_RSP_AUDIO] * 2;
u32 max_rdp = MAX(MAX(microseconds[PROFILER_TIME_TMEM], microseconds[PROFILER_TIME_CMD]), microseconds[PROFILER_TIME_PIPE]);
// u32 total_rsp = microseconds[PROFILER_TIME_RSP_GFX] + microseconds[PROFILER_TIME_RSP_AUDIO];
// u32 max_rdp = MAX(MAX(microseconds[PROFILER_TIME_TMEM], microseconds[PROFILER_TIME_CMD]), microseconds[PROFILER_TIME_PIPE]);
sprintf(text_buffer,
"FPS: %5.2f\n"
@@ -280,14 +281,14 @@ void profiler_print_times() {
" Camera\t\t%d\n"
#endif
"\n"
"RDP\t\t%d (%d%%)\n"
" Tmem\t\t\t%d\n"
" Cmd\t\t\t%d\n"
" Pipe\t\t\t%d\n"
"\n"
"RSP\t\t%d (%d%%)\n"
" Gfx\t\t\t%d\n"
" Audio\t\t\t%d\n",
"%.8X %.8X\n"
"%.8X %.8X\n"
"%.8X %.8X\n"
"%.8X %.8X\n"
"%.8X %.8X\n"
"%.8X %.8X\n"
"%.8X %.8X\n"
"%.8X %.8X\n",
1000000.0f / microseconds[PROFILER_TIME_FPS],
total_cpu, total_cpu / 333,
microseconds[PROFILER_TIME_CONTROLLERS],
@@ -303,13 +304,14 @@ void profiler_print_times() {
#ifdef PUPPYPRINT_DEBUG
microseconds[PROFILER_TIME_CAMERA],
#endif
max_rdp, max_rdp / 333,
microseconds[PROFILER_TIME_TMEM],
microseconds[PROFILER_TIME_CMD],
microseconds[PROFILER_TIME_PIPE],
total_rsp, total_rsp / 333,
microseconds[PROFILER_TIME_RSP_GFX],
microseconds[PROFILER_TIME_RSP_AUDIO] * 2
IO_READ(PIF_RAM_START + 0), IO_READ(PIF_RAM_START + 4),
IO_READ(PIF_RAM_START + 8), IO_READ(PIF_RAM_START + 12),
IO_READ(PIF_RAM_START + 16), IO_READ(PIF_RAM_START + 20),
IO_READ(PIF_RAM_START + 24), IO_READ(PIF_RAM_START + 28),
IO_READ(PIF_RAM_START + 32), IO_READ(PIF_RAM_START + 36),
IO_READ(PIF_RAM_START + 40), IO_READ(PIF_RAM_START + 44),
IO_READ(PIF_RAM_START + 48), IO_READ(PIF_RAM_START + 52),
IO_READ(PIF_RAM_START + 56), IO_READ(PIF_RAM_START + 60)
);
drawSmallStringDL(10, 8, text_buffer);

View File

@@ -349,7 +349,7 @@ static void thread6_rumble_loop(UNUSED void* arg) {
osRecvMesg(&gRumbleThreadVIMesgQueue, &msg, OS_MESG_BLOCK);
for (int channel = 0; channel < __osMaxControllers; channel++) {
if (gPortInfo[channel].plugged) {
if (gControllerStatuses[channel].type != CONT_NONE) {
struct RumbleInfo* info = &gRumbleInfos[channel];
update_rumble_data_queue(info);