diff options
| author | Tharo <17233964+Thar0@users.noreply.github.com> | 2022-09-03 01:52:13 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-03 02:52:13 +0200 |
| commit | 6b77ddba5ae0941c10c58260c44270dfcb88e182 (patch) | |
| tree | 824d27ec4e9d60eca657b2739c8ddf7fab17a90d /src/code/padmgr.c | |
| parent | c0cf83a814d13a9a07a2ca260203134fc4c5b735 (diff) | |
More documentation for padmgr.c (#1336)
* More documentation for padmgr.c
* Update comments
* Further suggested changes
* Suggested changes
* LOG_SEVERITY_INFO -> LOG_SEVERITY_CRITICAL
* Adjust PadMgr_RequestPadData comment
* Avoid array notation for args, adjust comment, rename the FaultMgr padInput field to inputs to better reflect it's an array
Diffstat (limited to 'src/code/padmgr.c')
| -rw-r--r-- | src/code/padmgr.c | 455 |
1 files changed, 285 insertions, 170 deletions
diff --git a/src/code/padmgr.c b/src/code/padmgr.c index 160a5301f..b8830d5a2 100644 --- a/src/code/padmgr.c +++ b/src/code/padmgr.c @@ -1,12 +1,74 @@ +/** + * @file padmgr.c + * + * This file implements communicating with joybus devices at a high level and serving the results to other threads. + * + * Any device that can be plugged into one of the four controller ports such as a standard N64 controller is a joybus + * device. Some joybus devices are also located inside the cartridge such as EEPROM for save data or the Real-Time + * Clock, however neither of these are used in Zelda64 and so this type of communication is unimplemented. Of the + * possible devices that can be plugged into the controller ports, the only device that padmgr will recognize and + * attempt to communicate with is the standard N64 controller. + * + * Communicating with these devices is broken down into various layers: + * + * Other threads : The rest of the program that will use the polled data + * | + * PadMgr : Manages devices, submits polling commands at vertical retrace + * | + * Libultra osCont* routines : Interface for building commands and safely using the Serial Interface + * | + * Serial Interface : Hardware unit for sending joybus commands and receiving data via DMA + * | + * PIF : Forwards joybus commands and receives response data from the devices + * |---¬---¬---¬-------¬ + * 1 2 3 4 5 : The joybus devices plugged into the four controller ports or on the cartridge + * + * Joybus communication is handled on another thread as polling and receiving controller data is a slow process; the + * N64 programming manual section 26.2.4.1 quotes 2 milliseconds as the expected delay from calling + * `osContStartReadData` to receiving the data. By running this on a separate thread to the game state, work can be + * done while waiting for this operation to complete. + */ #include "global.h" #include "vt.h" -s32 D_8012D280 = 1; - -OSMesgQueue* PadMgr_LockSerialMesgQueue(PadMgr* padMgr) { +#define PADMGR_LOG(controllerNo, msg) \ + if (1) { \ + osSyncPrintf(VT_FGCOL(YELLOW)); \ + /* padmgr: Controller %d: %s */ \ + osSyncPrintf("padmgr: %dコン: %s\n", (controllerNo) + 1, (msg)); \ + osSyncPrintf(VT_RST); \ + } \ + (void)0 + +#define LOG_SEVERITY_NOLOG 0 +#define LOG_SEVERITY_CRITICAL 1 +#define LOG_SEVERITY_ERROR 2 +#define LOG_SEVERITY_VERBOSE 3 + +s32 gPadMgrLogSeverity = LOG_SEVERITY_CRITICAL; + +/** + * Acquires exclusive access to the serial event queue. + * + * When a DMA to/from PIF RAM completes, an SI interrupt is generated to notify the process that the DMA has completed + * and a message is posted to the serial event queue. If multiple processes are trying to use the SI at the same time + * it becomes ambiguous as to which DMA has completed, so a locking system is required to arbitrate access to the SI. + * + * Once the task requiring the serial event queue is complete, it should be released with a call to + * `PadMgr_ReleaseSerialEventQueue()`. + * + * If another process tries to acquire the event queue, the current thread will be blocked until the event queue is + * released. Note the possibility for a deadlock, if the thread that already holds the serial event queue attempts to + * acquire it again it will block forever. + * + * @return The message queue to which SI interrupt events are posted. + * + * @see PadMgr_ReleaseSerialEventQueue + */ +OSMesgQueue* PadMgr_AcquireSerialEventQueue(PadMgr* padMgr) { OSMesgQueue* serialEventQueue = NULL; - if (D_8012D280 > 2) { + if (gPadMgrLogSeverity >= LOG_SEVERITY_VERBOSE) { // "serialMsgQ Waiting for lock" osSyncPrintf("%2d %d serialMsgQロック待ち %08x %08x %08x\n", osGetThreadId(NULL), MQ_GET_COUNT(&padMgr->serialLockQueue), padMgr, &padMgr->serialLockQueue, &serialEventQueue); @@ -14,7 +76,7 @@ OSMesgQueue* PadMgr_LockSerialMesgQueue(PadMgr* padMgr) { osRecvMesg(&padMgr->serialLockQueue, (OSMesg*)&serialEventQueue, OS_MESG_BLOCK); - if (D_8012D280 > 2) { + if (gPadMgrLogSeverity >= LOG_SEVERITY_VERBOSE) { // "serialMsgQ Locked" osSyncPrintf("%2d %d serialMsgQをロックしました %08x\n", osGetThreadId(NULL), MQ_GET_COUNT(&padMgr->serialLockQueue), serialEventQueue); @@ -23,8 +85,15 @@ OSMesgQueue* PadMgr_LockSerialMesgQueue(PadMgr* padMgr) { return serialEventQueue; } -void PadMgr_UnlockSerialMesgQueue(PadMgr* padMgr, OSMesgQueue* serialEventQueue) { - if (D_8012D280 > 2) { +/** + * Relinquishes access to the serial message queue, allowing another process to acquire and use it. + * + * @param serialEventQueue The serial message queue acquired by `PadMgr_AcquireSerialEventQueue` + * + * @see PadMgr_AcquireSerialEventQueue + */ +void PadMgr_ReleaseSerialEventQueue(PadMgr* padMgr, OSMesgQueue* serialEventQueue) { + if (gPadMgrLogSeverity >= LOG_SEVERITY_VERBOSE) { // "serialMsgQ Unlock" osSyncPrintf("%2d %d serialMsgQロック解除します %08x %08x %08x\n", osGetThreadId(NULL), MQ_GET_COUNT(&padMgr->serialLockQueue), padMgr, &padMgr->serialLockQueue, serialEventQueue); @@ -32,97 +101,99 @@ void PadMgr_UnlockSerialMesgQueue(PadMgr* padMgr, OSMesgQueue* serialEventQueue) osSendMesg(&padMgr->serialLockQueue, (OSMesg)serialEventQueue, OS_MESG_BLOCK); - if (D_8012D280 > 2) { + if (gPadMgrLogSeverity >= LOG_SEVERITY_VERBOSE) { // "serialMsgQ Unlocked" osSyncPrintf("%2d %d serialMsgQロック解除しました %08x %08x %08x\n", osGetThreadId(NULL), MQ_GET_COUNT(&padMgr->serialLockQueue), padMgr, &padMgr->serialLockQueue, serialEventQueue); } } +/** + * Locks controller input data while padmgr is reading new inputs or another thread is using the current inputs. + * This prevents new inputs overwriting the current inputs while they are in use. + * + * @see PadMgr_UnlockPadData + */ void PadMgr_LockPadData(PadMgr* padMgr) { osRecvMesg(&padMgr->lockQueue, NULL, OS_MESG_BLOCK); } +/** + * Unlocks controller input data, allowing padmgr to read new inputs or another thread to access the most recently + * polled inputs. + * + * @see PadMgr_LockPadData + */ void PadMgr_UnlockPadData(PadMgr* padMgr) { osSendMesg(&padMgr->lockQueue, NULL, OS_MESG_BLOCK); } -void PadMgr_RumbleControl(PadMgr* padMgr) { - static u32 errcnt = 0; - static u32 frame; - s32 temp = 1; +/** + * Activates the rumble pak for all controllers it is enabled on, stops it for all controllers it is disabled on and + * attempts to initialize it for a controller if it is not already initialized. + */ +void PadMgr_UpdateRumble(PadMgr* padMgr) { + static u32 sRumbleErrorCount = 0; // original name: "errcnt" + static u32 sRumbleUpdateCounter; + s32 motorStart = MOTOR_START; // required for matching? s32 triedRumbleComm; - OSMesgQueue* serialEventQueue = PadMgr_LockSerialMesgQueue(padMgr); - s32 var4; + OSMesgQueue* serialEventQueue = PadMgr_AcquireSerialEventQueue(padMgr); + s32 ret; s32 i; - triedRumbleComm = 0; + triedRumbleComm = false; - for (i = 0; i < 4; i++) { + for (i = 0; i < MAXCONTROLLERS; i++) { if (padMgr->ctrlrIsConnected[i]) { - if (padMgr->padStatus[i].status & 1) { - if (padMgr->pakType[i] == temp) { - if (padMgr->rumbleEnable[i] != 0) { - if (padMgr->rumbleCounter[i] < 3) { - // clang-format off - if (1) {} osSyncPrintf(VT_FGCOL(YELLOW)); - // clang-format on - - // "Vibration pack jumble jumble"? - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "振動パック ぶるぶるぶるぶる"); - osSyncPrintf(VT_RST); - - if (__osMotorAccess(&padMgr->pfs[i], temp) != 0) { - padMgr->pakType[i] = 0; - osSyncPrintf(VT_FGCOL(YELLOW)); + // Check status for whether a controller pak is connected + if (padMgr->padStatus[i].status & CONT_CARD_ON) { + if (padMgr->pakType[i] == CONT_PAK_RUMBLE) { + if (padMgr->rumbleEnable[i]) { + if (padMgr->rumbleTimer[i] < 3) { + // "Rumble pack brrr" + PADMGR_LOG(i, "振動パック ぶるぶるぶるぶる"); + + // This should be the osMotorStart macro, however the temporary variable motorStart is + // currently required for matching + if (__osMotorAccess(&padMgr->rumblePfs[i], motorStart) != 0) { + padMgr->pakType[i] = CONT_PAK_NONE; + // "A communication error has occurred with the vibration pack" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "振動パックで通信エラーが発生しました"); - osSyncPrintf(VT_RST); + PADMGR_LOG(i, "振動パックで通信エラーが発生しました"); } else { - padMgr->rumbleCounter[i] = 3; + padMgr->rumbleTimer[i] = 3; } - triedRumbleComm = 1; + triedRumbleComm = true; } } else { - if (padMgr->rumbleCounter[i] != 0) { - // clang-format off - if (1) {} osSyncPrintf(VT_FGCOL(YELLOW)); - // clang-format on - + if (padMgr->rumbleTimer[i] != 0) { // "Stop vibration pack" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "振動パック 停止"); - osSyncPrintf(VT_RST); + PADMGR_LOG(i, "振動パック 停止"); + + if (osMotorStop(&padMgr->rumblePfs[i]) != 0) { + padMgr->pakType[i] = CONT_PAK_NONE; - if (osMotorStop(&padMgr->pfs[i]) != 0) { - padMgr->pakType[i] = 0; - osSyncPrintf(VT_FGCOL(YELLOW)); // "A communication error has occurred with the vibration pack" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "振動パックで通信エラーが発生しました"); - osSyncPrintf(VT_RST); + PADMGR_LOG(i, "振動パックで通信エラーが発生しました"); } else { - padMgr->rumbleCounter[i]--; + padMgr->rumbleTimer[i]--; } - triedRumbleComm = 1; + triedRumbleComm = true; } } } } else { - if (padMgr->pakType[i] != 0) { - if (padMgr->pakType[i] == 1) { - osSyncPrintf(VT_FGCOL(YELLOW)); + if (padMgr->pakType[i] != CONT_PAK_NONE) { + if (padMgr->pakType[i] == CONT_PAK_RUMBLE) { // "It seems that a vibration pack was pulled out" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "振動パックが抜かれたようです"); - osSyncPrintf(VT_RST); - padMgr->pakType[i] = 0; + PADMGR_LOG(i, "振動パックが抜かれたようです"); + padMgr->pakType[i] = CONT_PAK_NONE; } else { - osSyncPrintf(VT_FGCOL(YELLOW)); // "It seems that a controller pack that is not a vibration pack was pulled out" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, - "振動パックではないコントローラパックが抜かれたようです"); - osSyncPrintf(VT_RST); - padMgr->pakType[i] = 0; + PADMGR_LOG(i, "振動パックではないコントローラパックが抜かれたようです"); + padMgr->pakType[i] = CONT_PAK_NONE; } } } @@ -130,128 +201,145 @@ void PadMgr_RumbleControl(PadMgr* padMgr) { } if (!triedRumbleComm) { - i = frame % 4; + // Try to initialize the rumble pak for controller port `i` if a controller pak is connected and + // not already known to be an initialized a rumble pak + i = sRumbleUpdateCounter % MAXCONTROLLERS; + + if (padMgr->ctrlrIsConnected[i] && (padMgr->padStatus[i].status & CONT_CARD_ON) && + padMgr->pakType[i] != CONT_PAK_RUMBLE) { + ret = osMotorInit(serialEventQueue, &padMgr->rumblePfs[i], i); - if (padMgr->ctrlrIsConnected[i] && (padMgr->padStatus[i].status & 1) && (padMgr->pakType[i] != 1)) { - var4 = osMotorInit(serialEventQueue, &padMgr->pfs[i], i); + if (ret == 0) { + padMgr->pakType[i] = CONT_PAK_RUMBLE; + osMotorStart(&padMgr->rumblePfs[i]); + osMotorStop(&padMgr->rumblePfs[i]); - if (var4 == 0) { - padMgr->pakType[i] = 1; - osMotorStart(&padMgr->pfs[i]); - osMotorStop(&padMgr->pfs[i]); - osSyncPrintf(VT_FGCOL(YELLOW)); // "Recognized vibration pack" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "振動パックを認識しました"); - osSyncPrintf(VT_RST); - } else if (var4 == 11) { - padMgr->pakType[i] = 2; - } else if (var4 == 4) { - LOG_NUM("++errcnt", ++errcnt, "../padmgr.c", 282); - osSyncPrintf(VT_FGCOL(YELLOW)); + PADMGR_LOG(i, "振動パックを認識しました"); + } else if (ret == PFS_ERR_DEVICE) { + padMgr->pakType[i] = CONT_PAK_OTHER; + } else if (ret == PFS_ERR_CONTRFAIL) { + LOG_NUM("++errcnt", ++sRumbleErrorCount, "../padmgr.c", 282); + // "Controller pack communication error" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "コントローラパックの通信エラー"); - osSyncPrintf(VT_RST); + PADMGR_LOG(i, "コントローラパックの通信エラー"); } } } + sRumbleUpdateCounter++; - frame++; - PadMgr_UnlockSerialMesgQueue(padMgr, serialEventQueue); + PadMgr_ReleaseSerialEventQueue(padMgr, serialEventQueue); } +/** + * Immediately stops rumble on all controllers + */ void PadMgr_RumbleStop(PadMgr* padMgr) { s32 i; - OSMesgQueue* serialEventQueue = PadMgr_LockSerialMesgQueue(padMgr); - - for (i = 0; i < 4; i++) { - if (osMotorInit(serialEventQueue, &padMgr->pfs[i], i) == 0) { - if ((gFaultMgr.msgId == 0) && (padMgr->rumbleOnFrames != 0)) { - osSyncPrintf(VT_FGCOL(YELLOW)); - // "Stop vibration pack" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "振動パック 停止"); - osSyncPrintf(VT_RST); - } + OSMesgQueue* serialEventQueue = PadMgr_AcquireSerialEventQueue(padMgr); + + for (i = 0; i < MAXCONTROLLERS; i++) { + if (osMotorInit(serialEventQueue, &padMgr->rumblePfs[i], i) == 0) { + // If there is a rumble pak attached to this controller, stop it - osMotorStop(&padMgr->pfs[i]); + if (gFaultMgr.msgId == 0 && padMgr->rumbleOnTimer != 0) { + // "Stop rumble pak" + PADMGR_LOG(i, "振動パック 停止"); + } + osMotorStop(&padMgr->rumblePfs[i]); } } - PadMgr_UnlockSerialMesgQueue(padMgr, serialEventQueue); + PadMgr_ReleaseSerialEventQueue(padMgr, serialEventQueue); } +/** + * Prevents rumble for 3 VI, ~0.05 seconds at 60 VI/sec + */ void PadMgr_RumbleReset(PadMgr* padMgr) { - padMgr->rumbleOffFrames = 3; + padMgr->rumbleOffTimer = 3; } -void PadMgr_RumbleSetSingle(PadMgr* padMgr, u32 ctrlr, u32 rumble) { - padMgr->rumbleEnable[ctrlr] = rumble; - padMgr->rumbleOnFrames = 240; +/** + * Enables or disables rumble on controller port `port` for 240 VI, + * ~4 seconds at 60 VI/sec and ~4.8 seconds at 50 VI/sec + */ +void PadMgr_RumbleSetSingle(PadMgr* padMgr, u32 port, u32 rumble) { + padMgr->rumbleEnable[port] = rumble; + padMgr->rumbleOnTimer = 240; } -void PadMgr_RumbleSet(PadMgr* padMgr, u8* ctrlrRumbles) { +/** + * Enables or disables rumble on all controller ports for 240 VI, + * ~4 seconds at 60 VI/sec and ~4.8 seconds at 50 VI/sec + * + * @param enable Array of u8 of length MAXCONTROLLERS containing either true or false to enable or disable rumble + * for that controller + */ +void PadMgr_RumbleSet(PadMgr* padMgr, u8* enable) { s32 i; - for (i = 0; i < 4; i++) { - padMgr->rumbleEnable[i] = ctrlrRumbles[i]; + for (i = 0; i < MAXCONTROLLERS; i++) { + padMgr->rumbleEnable[i] = enable[i]; } - padMgr->rumbleOnFrames = 240; + padMgr->rumbleOnTimer = 240; } -void PadMgr_ProcessInputs(PadMgr* padMgr) { +/** + * Updates `padMgr->inputs` based on the error response of each controller + */ +void PadMgr_UpdateInputs(PadMgr* padMgr) { s32 i; Input* input; - OSContPad* padnow1; // original name + OSContPad* pad; // original name: "padnow1" s32 buttonDiff; PadMgr_LockPadData(padMgr); - input = &padMgr->inputs[0]; - padnow1 = &padMgr->pads[0]; - - for (i = 0; i < padMgr->nControllers; i++, input++, padnow1++) { + for (input = &padMgr->inputs[0], pad = &padMgr->pads[0], i = 0; i < padMgr->nControllers; i++, input++, pad++) { input->prev = input->cur; - if (1) {} // Necessary to match - - switch (padnow1->errno) { + switch (pad->errno) { case 0: - input->cur = *padnow1; + // No error, copy inputs + input->cur = *pad; if (!padMgr->ctrlrIsConnected[i]) { padMgr->ctrlrIsConnected[i] = true; - osSyncPrintf(VT_FGCOL(YELLOW)); - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "認識しました"); // "Recognized" - osSyncPrintf(VT_RST); + // "Recognized" + PADMGR_LOG(i, "認識しました"); } break; - case 4: + case (CHNL_ERR_OVERRUN >> 4): + // Overrun error, reuse previous inputs input->cur = input->prev; LOG_NUM("this->Key_switch[i]", padMgr->ctrlrIsConnected[i], "../padmgr.c", 380); - osSyncPrintf(VT_FGCOL(YELLOW)); // "Overrun error occurred" - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "オーバーランエラーが発生"); - osSyncPrintf(VT_RST); + PADMGR_LOG(i, "オーバーランエラーが発生"); break; - case 8: + case (CHNL_ERR_NORESP >> 4): + // No response error, take inputs as 0 input->cur.button = 0; input->cur.stick_x = 0; input->cur.stick_y = 0; - input->cur.errno = padnow1->errno; + input->cur.errno = pad->errno; if (padMgr->ctrlrIsConnected[i]) { + // If we get no response, consider the controller disconnected padMgr->ctrlrIsConnected[i] = false; - padMgr->pakType[i] = 0; - padMgr->rumbleCounter[i] = 0xFF; - osSyncPrintf(VT_FGCOL(YELLOW)); - // "Do not respond"? - osSyncPrintf("padmgr: %dコン: %s\n", i + 1, "応答しません"); - osSyncPrintf(VT_RST); + padMgr->pakType[i] = CONT_PAK_NONE; + padMgr->rumbleTimer[i] = UINT8_MAX; + // "Not responding" + PADMGR_LOG(i, "応答しません"); } break; default: - LOG_HEX("padnow1->errno", padnow1->errno, "../padmgr.c", 396); + // Unknown error response + LOG_HEX("padnow1->errno", pad->errno, "../padmgr.c", 396); Fault_AddHungupAndCrash("../padmgr.c", 397); + break; } + // Calculate pressed and relative inputs buttonDiff = input->prev.button ^ input->cur.button; input->press.button |= (u16)(buttonDiff & input->cur.button); input->rel.button |= (u16)(buttonDiff & input->prev.button); @@ -263,29 +351,43 @@ void PadMgr_ProcessInputs(PadMgr* padMgr) { PadMgr_UnlockPadData(padMgr); } -void PadMgr_HandleRetraceMsg(PadMgr* padMgr) { +void PadMgr_HandleRetrace(PadMgr* padMgr) { s32 i; - OSMesgQueue* serialEventQueue = PadMgr_LockSerialMesgQueue(padMgr); + OSMesgQueue* serialEventQueue = PadMgr_AcquireSerialEventQueue(padMgr); u32 mask; + // Begin reading controller data osContStartReadData(serialEventQueue); - if (padMgr->retraceCallback) { + + // Execute retrace callback + if (padMgr->retraceCallback != NULL) { padMgr->retraceCallback(padMgr, padMgr->retraceCallbackValue); } + + // Wait for controller data osRecvMesg(serialEventQueue, NULL, OS_MESG_BLOCK); osContGetReadData(padMgr->pads); - if (padMgr->preNMIShutdown) { + + // If resetting, clear all controllers + if (padMgr->isResetting) { bzero(padMgr->pads, sizeof(padMgr->pads)); } - PadMgr_ProcessInputs(padMgr); + + // Update input data + PadMgr_UpdateInputs(padMgr); + + // Query controller status for all controllers osContStartQuery(serialEventQueue); osRecvMesg(serialEventQueue, NULL, OS_MESG_BLOCK); osContGetQuery(padMgr->padStatus); - PadMgr_UnlockSerialMesgQueue(padMgr, serialEventQueue); + PadMgr_ReleaseSerialEventQueue(padMgr, serialEventQueue); + + // Update the state of connected controllers mask = 0; - for (i = 0; i < 4; i++) { + for (i = 0; i < MAXCONTROLLERS; i++) { if (padMgr->padStatus[i].errno == 0) { + // Only standard N64 controllers are supported if (padMgr->padStatus[i].type == CONT_TYPE_NORMAL) { mask |= 1 << i; } else { @@ -298,53 +400,64 @@ void PadMgr_HandleRetraceMsg(PadMgr* padMgr) { padMgr->validCtrlrsMask = mask; if (gFaultMgr.msgId != 0) { + // If fault is active, no rumble PadMgr_RumbleStop(padMgr); - } else if (padMgr->rumbleOffFrames > 0) { - --padMgr->rumbleOffFrames; + } else if (padMgr->rumbleOffTimer > 0) { + // If the rumble off timer is active, no rumble + --padMgr->rumbleOffTimer; PadMgr_RumbleStop(padMgr); - } else if (padMgr->rumbleOnFrames == 0) { + } else if (padMgr->rumbleOnTimer == 0) { + // If the rumble on timer is inactive, no rumble PadMgr_RumbleStop(padMgr); - } else if (!padMgr->preNMIShutdown) { - PadMgr_RumbleControl(padMgr); - --padMgr->rumbleOnFrames; + } else if (!padMgr->isResetting) { + // If not resetting, update rumble + PadMgr_UpdateRumble(padMgr); + --padMgr->rumbleOnTimer; } } void PadMgr_HandlePreNMI(PadMgr* padMgr) { osSyncPrintf("padmgr_HandlePreNMI()\n"); - padMgr->preNMIShutdown = true; + padMgr->isResetting = true; PadMgr_RumbleReset(padMgr); } -void PadMgr_RequestPadData(PadMgr* padMgr, Input* inputs, s32 mode) { +/** + * Fetches the most recently polled inputs from padmgr + * + * @param inputs Array of Input of length MAXCONTROLLERS to copy inputs into + * @param gamePoll True if polling inputs for updating the game state + */ +void PadMgr_RequestPadData(PadMgr* padMgr, Input* inputs, s32 gameRequest) { s32 i; - Input* ogInput; - Input* newInput; + Input* inputIn; + Input* inputOut; s32 buttonDiff; PadMgr_LockPadData(padMgr); - ogInput = &padMgr->inputs[0]; - newInput = &inputs[0]; - for (i = 0; i < 4; i++) { - if (mode != 0) { - *newInput = *ogInput; - ogInput->press.button = 0; - ogInput->press.stick_x = 0; - ogInput->press.stick_y = 0; - ogInput->rel.button = 0; + for (inputIn = &padMgr->inputs[0], inputOut = &inputs[0], i = 0; i < MAXCONTROLLERS; i++, inputIn++, inputOut++) { + if (gameRequest) { + // Copy inputs as-is, press and rel are calculated prior in `PadMgr_UpdateInputs` + *inputOut = *inputIn; + // Zero parts of the press and rel inputs in the polled inputs so they are not read more than once + inputIn->press.button = 0; + inputIn->press.stick_x = 0; + inputIn->press.stick_y = 0; + inputIn->rel.button = 0; } else { - newInput->prev = newInput->cur; - newInput->cur = ogInput->cur; - buttonDiff = newInput->prev.button ^ newInput->cur.button; - newInput->press.button = newInput->cur.button & buttonDiff; - newInput->rel.button = newInput->prev.button & buttonDiff; - PadUtils_UpdateRelXY(newInput); - newInput->press.stick_x += (s8)(newInput->cur.stick_x - newInput->prev.stick_x); - newInput->press.stick_y += (s8)(newInput->cur.stick_y - newInput->prev.stick_y); + // Take as the previous inputs the inputs that are currently in the destination array + inputOut->prev = inputOut->cur; + // Copy current inputs from the polled inputs + inputOut->cur = inputIn->cur; + // Calculate press and rel from these + buttonDiff = inputOut->prev.button ^ inputOut->cur.button; + inputOut->press.button = inputOut->cur.button & buttonDiff; + inputOut->rel.button = inputOut->prev.button & buttonDiff; + PadUtils_UpdateRelXY(inputOut); + inputOut->press.stick_x += (s8)(inputOut->cur.stick_x - inputOut->prev.stick_x); + inputOut->press.stick_y += (s8)(inputOut->cur.stick_y - inputOut->prev.stick_y); } - ogInput++; - newInput++; } PadMgr_UnlockPadData(padMgr); @@ -358,7 +471,7 @@ void PadMgr_ThreadEntry(PadMgr* padMgr) { exit = false; while (!exit) { - if ((D_8012D280 > 2) && MQ_IS_EMPTY(&padMgr->interruptQueue)) { + if (gPadMgrLogSeverity >= LOG_SEVERITY_VERBOSE && MQ_IS_EMPTY(&padMgr->interruptQueue)) { // "Waiting for controller thread event" osSyncPrintf("コントローラスレッドイベント待ち %lld\n", OS_CYCLES_TO_USEC(osGetTime())); } @@ -368,16 +481,15 @@ void PadMgr_ThreadEntry(PadMgr* padMgr) { switch (*msg) { case OS_SC_RETRACE_MSG: - if (D_8012D280 > 2) { + if (gPadMgrLogSeverity >= LOG_SEVERITY_VERBOSE) { osSyncPrintf("padmgr_HandleRetraceMsg START %lld\n", OS_CYCLES_TO_USEC(osGetTime())); } - PadMgr_HandleRetraceMsg(padMgr); + PadMgr_HandleRetrace(padMgr); - if (D_8012D280 > 2) { + if (gPadMgrLogSeverity >= LOG_SEVERITY_VERBOSE) { osSyncPrintf("padmgr_HandleRetraceMsg END %lld\n", OS_CYCLES_TO_USEC(osGetTime())); } - break; case OS_SC_PRE_NMI_MSG: PadMgr_HandlePreNMI(padMgr); @@ -401,13 +513,16 @@ void PadMgr_Init(PadMgr* padMgr, OSMesgQueue* serialEventQueue, IrqMgr* irqMgr, osCreateMesgQueue(&padMgr->interruptQueue, padMgr->interruptMsgBuf, ARRAY_COUNT(padMgr->interruptMsgBuf)); IrqMgr_AddClient(padMgr->irqMgr, &padMgr->irqClient, &padMgr->interruptQueue); - osCreateMesgQueue(&padMgr->serialLockQueue, padMgr->serialLockMsgBuf, ARRAY_COUNT(padMgr->serialLockMsgBuf)); - PadMgr_UnlockSerialMesgQueue(padMgr, serialEventQueue); - osCreateMesgQueue(&padMgr->lockQueue, padMgr->lockMsgBuf, ARRAY_COUNT(padMgr->lockMsgBuf)); + + osCreateMesgQueue(&padMgr->serialLockQueue, &padMgr->serialMsg, 1); + PadMgr_ReleaseSerialEventQueue(padMgr, serialEventQueue); + + osCreateMesgQueue(&padMgr->lockQueue, &padMgr->lockMsg, 1); PadMgr_UnlockPadData(padMgr); + PadSetup_Init(serialEventQueue, (u8*)&padMgr->validCtrlrsMask, padMgr->padStatus); - padMgr->nControllers = 4; + padMgr->nControllers = MAXCONTROLLERS; osContSetCh(padMgr->nControllers); osCreateThread(&padMgr->thread, id, (void (*)(void*))PadMgr_ThreadEntry, padMgr, stack, priority); |
