diff --git a/include/functions.h b/include/functions.h index 11c79548a8..35010d601f 100644 --- a/include/functions.h +++ b/include/functions.h @@ -328,7 +328,7 @@ OSTime osGetTime(void); void guRotateF(float m[4][4], f32 a, f32 x, f32 y, f32 z); void guRotate(Mtx* m, f32 a, f32 x, f32 y, f32 z); void __osSetGlobalIntMask(u32 mask); -// void osVoiceInit(void); +s32 osVoiceInit(OSMesgQueue* mq, OSVoiceHandle* handle, s32 channel); s32 __osContChannelReset(OSMesgQueue* mq, s32 channel); // void __osVoiceSetADConverter(void); s32 osAiSetFrequency(u32 frequency); @@ -2098,34 +2098,6 @@ ListAlloc* ListAlloc_Init(ListAlloc* this); // void ListAlloc_Free(void); void ListAlloc_FreeAll(ListAlloc* this); void Main(void* arg); -u32 Padmgr_GetControllerBitmask(void); -void func_80174F24(void (*arg0)(void*), void* arg1); -void func_80174F44(void (*arg0)(void*), void* arg1); -void func_80174F7C(void (*arg0)(s32), void* arg1); -void func_80174F9C(void (*arg0)(s32), void* arg1); -// OSMesgQueue* Padmgr_GetEventCallback(void); -// void func_80175008(void); -void Padmgr_SetEventCallback(OSMesg pvParm1); -// void func_8017506C(void); -// void Padmgr_Lock(void); -// void Padmgr_Unlock(void); -// void func_801750FC(void); -// void func_80175364(void); -void func_80175434(void); -void func_8017544C(s32 port, s32 rumbleOn); -void PadMgr_RumbleSet(u8 rumbleEnabled[MAXCONTROLLERS]); -s32 PadMgr_ControllerHasRumblePak(s32 port); -void Padmgr_CalcStickEdges(Input* input); -// void Padmgr_ParseState(void); -// void func_801759BC(void); -// void func_80175AE0(void); -// void Padmgr_Update(void); -// void Padmgr_Stop(void); -void func_80175E68(Input* input, s32 param_2); -void Padmgr_GetInput(Input* input, s32 param_2); -void Padmgr_GetInput2(Input* input, s32 param_2); -void Padmgr_ThreadEntry(PadMgr* padmgr); -void PadMgr_Init(OSMesgQueue* siEventCallbackQueue, IrqMgr* irqmgr, OSId threadId, OSPri threadPri, void* stack); void Sched_SwapFramebuffer(CfbInfo* cfbInfo); void Sched_RetraceUpdateFramebuffer(SchedContext* sched, CfbInfo* cfbInfo); void Sched_HandleReset(SchedContext* sched); @@ -2614,7 +2586,7 @@ void Audio_ResetForAudioHeapStep3(void); void Audio_ResetForAudioHeapStep2(void); void Audio_ResetForAudioHeapStep1(s32 specId); -// void func_801A4EB0(void); +void func_801A4EB0(void); // void func_801A4EB8(void); void func_801A4FD8(void); void func_801A5080(u16 arg0); diff --git a/include/io/controller.h b/include/io/controller.h index 4321df0966..b588b41984 100644 --- a/include/io/controller.h +++ b/include/io/controller.h @@ -35,10 +35,6 @@ #define CONT_CMD_WRITE_EEPROM_RX 1 #define CONT_CMD_RESET_RX 3 -#define CONT_CMD_NOP 0xFF -#define CONT_CMD_END 0xFE // Indicates end of a command -#define CONT_CMD_EXE 1 // Set pif ram status byte to this to do a command - #define CONT_ERR_NO_CONTROLLER PFS_ERR_NOPACK /* 1 */ #define CONT_ERR_CONTRFAIL CONT_OVERRUN_ERROR /* 4 */ #define CONT_ERR_INVALID PFS_ERR_INVALID /* 5 */ @@ -48,6 +44,52 @@ #define CONT_ERR_VOICE_WORD 14 #define CONT_ERR_VOICE_NO_RESPONSE 15 +// Joybus commands +#define CONT_CMD_REQUEST_STATUS 0 +#define CONT_CMD_READ_BUTTON 1 +#define CONT_CMD_READ_PAK 2 +#define CONT_CMD_WRITE_PAK 3 +#define CONT_CMD_READ_EEPROM 4 +#define CONT_CMD_WRITE_EEPROM 5 +#define CONT_CMD_READ36_VOICE 9 +#define CONT_CMD_WRITE20_VOICE 10 +#define CONT_CMD_READ2_VOICE 11 +#define CONT_CMD_WRITE4_VOICE 12 +#define CONT_CMD_SWRITE_VOICE 13 +#define CONT_CMD_CHANNEL_RESET 0xFD +#define CONT_CMD_RESET 0xFF + +// Bytes transmitted for each joybus command +#define CONT_CMD_REQUEST_STATUS_TX 1 +#define CONT_CMD_READ_BUTTON_TX 1 +#define CONT_CMD_READ_PAK_TX 3 +#define CONT_CMD_WRITE_PAK_TX 35 +#define CONT_CMD_READ_EEPROM_TX 2 +#define CONT_CMD_WRITE_EEPROM_TX 10 +#define CONT_CMD_READ36_VOICE_TX 3 +#define CONT_CMD_WRITE20_VOICE_TX 23 +#define CONT_CMD_READ2_VOICE_TX 3 +#define CONT_CMD_WRITE4_VOICE_TX 7 +#define CONT_CMD_SWRITE_VOICE_TX 3 +#define CONT_CMD_RESET_TX 1 + +// Bytes received for each joybus command +#define CONT_CMD_REQUEST_STATUS_RX 3 +#define CONT_CMD_READ_BUTTON_RX 4 +#define CONT_CMD_READ_PAK_RX 33 +#define CONT_CMD_WRITE_PAK_RX 1 +#define CONT_CMD_READ_EEPROM_RX 8 +#define CONT_CMD_WRITE_EEPROM_RX 1 +#define CONT_CMD_READ36_VOICE_RX 37 +#define CONT_CMD_WRITE20_VOICE_RX 1 +#define CONT_CMD_READ2_VOICE_RX 3 +#define CONT_CMD_WRITE4_VOICE_RX 1 +#define CONT_CMD_SWRITE_VOICE_RX 1 +#define CONT_CMD_RESET_RX 3 + +#define CONT_CMD_NOP 0xFF +#define CONT_CMD_END 0xFE // Indicates end of a command +#define CONT_CMD_EXE 1 // Set pif ram status byte to this to do a command #define DIR_STATUS_EMPTY 0 #define DIR_STATUS_UNKNOWN 1 @@ -81,6 +123,26 @@ #define CONT_ADDR_CRC_ER 0x04 #define CONT_EEPROM_BUSY 0x80 +// Accessory detection +#define CONT_ADDR_DETECT 0x8000 +// Rumble +#define CONT_ADDR_RUMBLE 0xC000 +// Controller Pak +// Transfer Pak +#define CONT_ADDR_GB_POWER 0x8000 // Same as the detection address, but semantically different +#define CONT_ADDR_GB_BANK 0xA000 +#define CONT_ADDR_GB_STATUS 0xB000 + +// Addresses sent to controller accessories are in blocks, not bytes +#define CONT_BLOCKS(x) ((x) / BLOCKSIZE) + +// Block addresses of the above +#define CONT_BLOCK_DETECT CONT_BLOCKS(CONT_ADDR_DETECT) +#define CONT_BLOCK_RUMBLE CONT_BLOCKS(CONT_ADDR_RUMBLE) +#define CONT_BLOCK_GB_POWER CONT_BLOCKS(CONT_ADDR_GB_POWER) +#define CONT_BLOCK_GB_BANK CONT_BLOCKS(CONT_ADDR_GB_BANK) +#define CONT_BLOCK_GB_STATUS CONT_BLOCKS(CONT_ADDR_GB_STATUS) + /* Buttons */ #define BTN_CRIGHT 0x0001 #define BTN_CLEFT 0x0002 @@ -88,6 +150,7 @@ #define BTN_CUP 0x0008 #define BTN_R 0x0010 #define BTN_L 0x0020 +#define BTN_RESET 0x0080 #define BTN_DRIGHT 0x0100 #define BTN_DLEFT 0x0200 #define BTN_DDOWN 0x0400 @@ -146,6 +209,8 @@ typedef struct { /* 0x26 */ u8 datacrc; } __OSContRamReadFormat; +#define READFORMAT(ptr) ((__OSContRamReadFormat*)(ptr)) + extern OSPifRam __osContPifRam; // extern UNK_TYPE1 D_8009CF0C; extern u8 __osContLastPoll; @@ -153,11 +218,4 @@ extern u8 __osMaxControllers; // extern OSMesgQueue D_8009CF38; // extern OSMesg D_8009CF50; -typedef struct { - /* 0x00 */ OSContPad cur; - /* 0x06 */ OSContPad prev; - /* 0x0C */ OSContPad press; // X/Y store delta from last frame - /* 0x12 */ OSContPad rel; // X/Y store adjusted -} Input; // size = 0x18 - #endif diff --git a/include/irqmgr.h b/include/irqmgr.h index 40ed322d13..ac2c74960c 100644 --- a/include/irqmgr.h +++ b/include/irqmgr.h @@ -1,9 +1,14 @@ #ifndef IRQMGR_H #define IRQMGR_H -#include "PR/ultratypes.h" #include "PR/sched.h" -#include "ultra64/message.h" +#include "os.h" +#include "ultra64.h" + +#define OS_SC_RETRACE_MSG 1 +#define OS_SC_DONE_MSG 2 +#define OS_SC_NMI_MSG 3 // name is made up, 3 is OS_SC_RDP_DONE_MSG in the original sched.c +#define OS_SC_PRE_NMI_MSG 4 typedef struct IrqMgrClient { /* 0x0 */ struct IrqMgrClient* next; diff --git a/include/padmgr.h b/include/padmgr.h new file mode 100644 index 0000000000..674c9bc4ed --- /dev/null +++ b/include/padmgr.h @@ -0,0 +1,97 @@ +#ifndef PADMGR_H +#define PADMGR_H + +#include "libc/stdbool.h" +#include "io/controller.h" +#include "irqmgr.h" + +typedef struct { + /* 0x00 */ OSContPad cur; + /* 0x06 */ OSContPad prev; + /* 0x0C */ OSContPad press; // X/Y store delta from last frame + /* 0x12 */ OSContPad rel; // X/Y store adjusted +} Input; // size = 0x18 + +typedef enum { + /* 0 */ PADMGR_CONT_NONE, + /* 1 */ PADMGR_CONT_NORMAL, + /* 3 */ PADMGR_CONT_MOUSE = 3, + /* 4 */ PADMGR_CONT_VOICE_PLUGGED, // VRU plugged but not initialized + /* 5 */ PADMGR_CONT_VOICE, + /* -1 */ PADMGR_CONT_UNK = 0xFF +} ControllerDeviceType; + +typedef enum { + /* 0 */ CONT_PAK_NONE, + /* 1 */ CONT_PAK_RUMBLE, + /* 2 */ CONT_PAK_OTHER +} ControllerPakType; + +typedef struct { + /* 0x000 */ u8 validCtrlrsMask; + /* 0x004 */ void (*rumbleRetraceCallback)(void*); + /* 0x008 */ void* rumbleRetraceArg; + /* 0x00C */ void (*inputRetraceCallback)(void*); + /* 0x010 */ void* inputRetraceArg; + /* 0x014 */ OSContStatus padStatus[MAXCONTROLLERS]; + /* 0x024 */ OSMesg serialMsg; + /* 0x028 */ OSMesg lockMsg; + /* 0x02C */ OSMesg interruptMsgBuf[8]; + /* 0x04C */ OSMesgQueue serialLockQueue; + /* 0x064 */ OSMesgQueue lockQueue; + /* 0x07C */ OSMesgQueue interruptQueue; + /* 0x094 */ IrqMgrClient irqClient; + /* 0x09C */ IrqMgr* irqMgr; + /* 0x0A0 */ OSThread thread; + /* 0x250 */ Input inputs[MAXCONTROLLERS]; + /* 0x2B0 */ OSContPad pads[MAXCONTROLLERS]; + /* 0x2C8 */ u8 nControllers; + /* 0x2C9 */ u8 ctrlrType[MAXCONTROLLERS]; // type of controller currently connected to each port + /* 0x2CD */ u8 pakType[MAXCONTROLLERS]; // type of controller pak for each port (if applicable) + /* 0x2D1 */ u8 rumbleEnable[MAXCONTROLLERS]; // whether rumble is active for each port + /* 0x2D5 */ u8 rumbleTimer[MAXCONTROLLERS]; + /* 0x2DC */ OSPfs rumblePfs[MAXCONTROLLERS]; + /* 0x47C */ vu8 rumbleOffTimer; // amount of VI retraces to not rumble for, takes priority over rumbleOnTimer + /* 0x47D */ vu8 rumbleOnTimer; // amount of VI retraces to rumble for + /* 0x47E */ u8 isResetting; +} PadMgr; // size = 0x480 + +extern PadMgr gPadMgr; + +// Initialization + +s32 PadSetup_Init(OSMesgQueue* mq, u8* outMask, OSContStatus* status); +void PadMgr_Init(OSMesgQueue* siEvtQ, IrqMgr* irqMgr, OSId threadId, OSPri pri, void* stack); + +// Fetching inputs + +void PadMgr_GetInputNoLock(Input* inputs, s32 gameRequest); +void PadMgr_GetInput(Input* inputs, s32 gameRequest); +void PadMgr_GetInput2(Input* inputs, s32 gameRequest); + +// Callbacks + +void PadMgr_SetRumbleRetraceCallback(void (*callback)(void*), void* arg); +void PadMgr_UnsetRumbleRetraceCallback(void (*callback)(void*), void* arg); + +void PadMgr_SetInputRetraceCallback(void (*callback)(void*), void* arg); +void PadMgr_UnsetInputRetraceCallback(void (*callback)(void*), void* arg); + +// Valid controllers + +u8 PadMgr_GetValidControllersMask(void); + +// Voice queue + +OSMesgQueue* PadMgr_VoiceAcquireSerialEventQueue(void); +void PadMgr_VoiceReleaseSerialEventQueue(OSMesgQueue* serialEventQueue); + +// Rumble + +void PadMgr_RumbleStop(void); +void PadMgr_RumblePause(void); +void PadMgr_RumbleSetSingle(s32 port, s32 enable); +void PadMgr_RumbleSet(u8 enable[MAXCONTROLLERS]); +s32 PadMgr_ControllerHasRumblePak(s32 port); + +#endif diff --git a/include/ultra64/motor.h b/include/ultra64/motor.h index ad68281324..ed969b3de4 100644 --- a/include/ultra64/motor.h +++ b/include/ultra64/motor.h @@ -5,13 +5,14 @@ #include "PR/pfs.h" #include "ultra64/message.h" -#define MOTOR_START 1 -#define MOTOR_STOP 0 +#define MOTOR_START 1 +#define MOTOR_STOP 0 -#define osMotorStart(x) __osMotorAccess((x), MOTOR_START) -#define osMotorStop(x) __osMotorAccess((x), MOTOR_STOP) +#define osMotorStart(x) __osMotorAccess((x), MOTOR_START) +#define osMotorStop(x) __osMotorAccess((x), MOTOR_STOP) -s32 __osMotorAccess(OSPfs* pfs, u32 vibrate); -s32 osMotorInit(OSMesgQueue* ctrlrqueue, OSPfs* pfs, s32 channel); +s32 __osMotorAccess(OSPfs* pfs, s32 flag); + +s32 osMotorInit(OSMesgQueue* mq, OSPfs* pfs, s32 channel); #endif diff --git a/include/ultra64/rcp.h b/include/ultra64/rcp.h index 6bd778ccfa..7a336be28c 100644 --- a/include/ultra64/rcp.h +++ b/include/ultra64/rcp.h @@ -11,4 +11,12 @@ #define DEVICE_TYPE_SRAM 3 /* SRAM */ #define DEVICE_TYPE_INIT 7 /* initial value */ + +#define CHNL_ERR_NORESP 0x80 /* Bit 7 (Rx): No response error */ +#define CHNL_ERR_OVERRUN 0x40 /* Bit 6 (Rx): Overrun error */ +#define CHNL_ERR_FRAME 0x80 /* Bit 7 (Tx): Frame error */ +#define CHNL_ERR_COLLISION 0x40 /* Bit 6 (Tx): Collision error */ + +#define CHNL_ERR_MASK 0xC0 /* Bit 6-7: channel errors */ + #endif diff --git a/include/variables.h b/include/variables.h index f540107b30..c8b511a7eb 100644 --- a/include/variables.h +++ b/include/variables.h @@ -795,9 +795,6 @@ extern u32 cfbIdx[3]; extern s32 gScreenWidth; extern s32 gScreenHeight; extern u32 startHeapSize; -extern PadMgr* padmgrContext; -// extern UNK_TYPE4 controllerInputsCaptured; -// extern UNK_TYPE4 D_801D1538; extern UNK_PTR D_801D1540; // extern f32 sFactorialTbl[13]; extern Vec3f gZeroVec3f; @@ -2410,7 +2407,6 @@ extern u32 gSegments[NUM_SEGMENTS]; extern SchedContext gSchedContext; extern OSThread gGraphThread; -extern PadMgr gPadMgr; extern FaultClient sSchedFaultClient; extern OSTime sRSPGFXStartTime; @@ -2616,7 +2612,7 @@ extern s32 D_801FD120; // extern UNK_TYPE1 D_801FD598; // extern UNK_TYPE1 D_801FD5A0; // extern UNK_TYPE1 D_801FD5A4; -// extern UNK_TYPE1 D_801FD5B8; +extern OSVoiceHandle gVoiceHandle; // extern UNK_TYPE1 D_801FD5C4; // extern UNK_TYPE1 D_801FD5C8; // extern UNK_TYPE1 D_801FD5E8; diff --git a/include/z64.h b/include/z64.h index 95af2c1579..e9bdcfe623 100644 --- a/include/z64.h +++ b/include/z64.h @@ -14,6 +14,7 @@ #include "osint.h" #include "os.h" #include "irqmgr.h" +#include "padmgr.h" #include "scheduler.h" #include "xstdio.h" @@ -481,7 +482,7 @@ typedef struct { /* 0x7D8 */ FaultClient* clients; /* 0x7DC */ FaultAddrConvClient* addrConvClients; /* 0x7E0 */ UNK_TYPE1 pad7E0[0x4]; - /* 0x7E4 */ Input padInput[4]; + /* 0x7E4 */ Input padInput[MAXCONTROLLERS]; /* 0x844 */ void* fb; } FaultThreadStruct; // size = 0x848 @@ -522,7 +523,7 @@ typedef struct GameState { /* 0x08 */ GameStateFunc destroy; /* 0x0C */ GameStateFunc init; // Usually the current game state's init, though after stopping, the graph thread will look here to determine the next game state to load. /* 0x10 */ size_t size; - /* 0x14 */ Input input[4]; + /* 0x14 */ Input input[MAXCONTROLLERS]; /* 0x74 */ TwoHeadArena heap; /* 0x84 */ GameAlloc alloc; /* 0x98 */ UNK_TYPE1 pad98[0x3]; @@ -541,34 +542,6 @@ typedef void (*ColChkApplyFunc)(struct PlayState*, CollisionCheckContext*, Colli typedef void (*ColChkVsFunc)(struct PlayState*, CollisionCheckContext*, Collider*, Collider*); typedef s32 (*ColChkLineFunc)(struct PlayState*, CollisionCheckContext*, Collider*, Vec3f*, Vec3f*); -typedef struct { - /* 0x000 */ u8 controllers; // bit 0 is set if controller 1 is plugged in, etc. - /* 0x001 */ UNK_TYPE1 pad1[0x13]; - /* 0x014 */ OSContStatus statuses[4]; - /* 0x024 */ UNK_TYPE4 unk24; - /* 0x028 */ OSMesg lockMesg[1]; - /* 0x02C */ OSMesg interrupts[8]; - /* 0x04C */ OSMesgQueue sSiIntMsgQ; - /* 0x064 */ OSMesgQueue lock; - /* 0x07C */ OSMesgQueue irqmgrCallbackQueue; - /* 0x094 */ IrqMgrClient irqmgrCallbackQueueNode; - /* 0x09C */ IrqMgr* irqmgr; - /* 0x0A0 */ OSThread thread; - /* 0x250 */ Input input[4]; - /* 0x2B0 */ OSContPad controllerState1[4]; - /* 0x2C8 */ u8 maxNumControllers; - /* 0x2C9 */ UNK_TYPE1 pad2C9[0x1B3]; - /* 0x47C */ u8 unk47C; - /* 0x47D */ u8 unk47D; - /* 0x47E */ u8 hasStopped; - /* 0x47F */ UNK_TYPE1 pad47F[0x1]; -} PadMgr; // size = 0x480 - -#define OS_SC_RETRACE_MSG 1 -#define OS_SC_DONE_MSG 2 -#define OS_SC_NMI_MSG 3 // name is made up, 3 is OS_SC_RDP_DONE_MSG in the original sched.c -#define OS_SC_PRE_NMI_MSG 4 - typedef struct { /* 0x000 */ IrqMgr* irqMgr; /* 0x004 */ SchedContext* sched; diff --git a/include/z64frameadvance.h b/include/z64frameadvance.h index c0feaed597..179a1adbaa 100644 --- a/include/z64frameadvance.h +++ b/include/z64frameadvance.h @@ -1,8 +1,7 @@ #ifndef Z64FRAMEADVANCE_H #define Z64FRAMEADVANCE_H -#include "ultra64.h" -#include "io/controller.h" +#include "padmgr.h" typedef struct FrameAdvanceContext { /* 0x0 */ s32 enabled; diff --git a/spec b/spec index 57fca6cdaf..ef85a17641 100644 --- a/spec +++ b/spec @@ -567,7 +567,6 @@ beginseg include "build/data/code/main.data.o" include "build/data/code/main.bss.o" include "build/src/code/padmgr.o" - include "build/data/code/padmgr.data.o" include "build/src/code/sched.o" include "build/src/code/speed_meter.o" include "build/data/code/speed_meter.data.o" diff --git a/src/audio/code_8019AF00.c b/src/audio/code_8019AF00.c index d107e65b72..287149c911 100644 --- a/src/audio/code_8019AF00.c +++ b/src/audio/code_8019AF00.c @@ -2058,11 +2058,11 @@ const char sAudioOcarinaUnusedText6[] = "last key step is too short !!! %d:%d %d const char sAudioOcarinaUnusedText7[] = "check is over!!! %d %d %d\n"; void AudioOcarina_ReadControllerInput(void) { - Input inputs[4]; + Input inputs[MAXCONTROLLERS]; Input* input = &inputs[0]; u32 ocarinaInputButtonPrev = sOcarinaInputButtonCur; - Padmgr_GetInput2(inputs, 0); + PadMgr_GetInput2(inputs, false); sOcarinaInputButtonCur = input->cur.button; sOcarinaInputButtonPrev = ocarinaInputButtonPrev; sOcarinaInputStickRel.x = input->rel.stick_x; diff --git a/src/boot_O2_g3/fault.c b/src/boot_O2_g3/fault.c index 2c8f4a6679..6e1656170b 100644 --- a/src/boot_O2_g3/fault.c +++ b/src/boot_O2_g3/fault.c @@ -204,7 +204,7 @@ void Fault_Sleep(u32 duration) { } void Fault_PadCallback(Input* input) { - Padmgr_GetInput2(input, 0); + PadMgr_GetInput2(input, false); } void Fault_UpdatePadImpl() { @@ -474,7 +474,7 @@ void Fault_WaitForButtonCombo(void) { do { Fault_Sleep(0x10); Fault_UpdatePadImpl(); - } while (!CHECK_BTN_ALL(input->press.button, 0x80)); + } while (!CHECK_BTN_ALL(input->press.button, BTN_RESET)); } while (!CHECK_BTN_ALL(input->cur.button, BTN_DLEFT | BTN_L | BTN_R | BTN_CRIGHT)); } @@ -763,7 +763,7 @@ void Fault_SetOptionsFromController3(void) { u32 graphRA; u32 graphSP; - if (CHECK_BTN_ALL(input3->press.button, 0x80)) { + if (CHECK_BTN_ALL(input3->press.button, BTN_RESET)) { faultCustomOptions = !faultCustomOptions; } diff --git a/src/code/game.c b/src/code/game.c index 3ff4f99628..bc8b9e39f3 100644 --- a/src/code/game.c +++ b/src/code/game.c @@ -128,7 +128,7 @@ void func_801736DC(GraphicsContext* gfxCtx) { } void Game_UpdateInput(GameState* gameState) { - Padmgr_GetInput(gameState->input, 1); + PadMgr_GetInput(gameState->input, true); } void Game_Update(GameState* gameState) { diff --git a/src/code/main.c b/src/code/main.c index 7fbb5ba393..6eadd591a7 100644 --- a/src/code/main.c +++ b/src/code/main.c @@ -26,7 +26,6 @@ extern StackEntry sSchedStackInfo; extern StackEntry sAudioStackInfo; extern StackEntry sPadMgrStackInfo; extern AudioMgr sAudioMgr; -extern PadMgr gPadMgr; void Main(void* arg) { intptr_t fb; diff --git a/src/code/padmgr.c b/src/code/padmgr.c index 077ef1b2b0..a04a14f579 100644 --- a/src/code/padmgr.c +++ b/src/code/padmgr.c @@ -1,58 +1,797 @@ +/** + * @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. Unlike the + * padmgr implementation in OoT, there are three controller types supported: + * - Standard N64 Controller + * - N64 Mouse + * - Voice Recognition Unit + * + * 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 "io/controller.h" #include "ultra64/motor.h" -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_GetControllerBitmask.s") +#define PADMGR_RETRACE_MSG (1 << 0) +#define PADMGR_PRE_NMI_MSG (1 << 1) +#define PADMGR_NMI_MSG (1 << 2) -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80174F24.s") +typedef enum { + /* 0 */ VOICE_INIT_FAILED, // voice initialization failed + /* 1 */ VOICE_INIT_TRY, // try to initialize voice + /* 2 */ VOICE_INIT_SUCCESS // voice initialized +} VoiceInitStatus; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80174F44.s") +PadMgr* sPadMgrInstance = &gPadMgr; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80174F7C.s") +s32 sPadMgrRetraceCount = 0; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80174F9C.s") +s32 sVoiceInitStatus = VOICE_INIT_TRY; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_GetEventCallback.s") +/** + * Returns the bitmask of valid controllers. + * + * bit n set = controller (n+1) available. + */ +u8 PadMgr_GetValidControllersMask(void) { + return sPadMgrInstance->validCtrlrsMask; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80175008.s") +/** + * Sets the callback function intended to be used to modify the rumble pak state on each VI with + * calls to `PadMgr_RumbleSetSingle`. The callback may be passed a single user-provided argument. + * + * @param callback callback to run before rumble state is updated for the current VI + * @param arg the argument to pass to the callback + * + * @see PadMgr_RumbleSetSingle + * @see PadMgr_UnsetRumbleRetraceCallback + */ +void PadMgr_SetRumbleRetraceCallback(void (*callback)(void*), void* arg) { + sPadMgrInstance->rumbleRetraceCallback = callback; + sPadMgrInstance->rumbleRetraceArg = arg; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_SetEventCallback.s") +/** + * Unsets the rumble retrace callback if the provided function and argument are the same as those already registered. + * + * @param callback the callback to test against + * @param arg the argument to test against + * + * @see PadMgr_SetRumbleRetraceCallback + */ +void PadMgr_UnsetRumbleRetraceCallback(void (*callback)(void*), void* arg) { + if ((sPadMgrInstance->rumbleRetraceCallback == callback) && (sPadMgrInstance->rumbleRetraceArg == arg)) { + sPadMgrInstance->rumbleRetraceCallback = NULL; + sPadMgrInstance->rumbleRetraceArg = NULL; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_8017506C.s") +/** + * Sets the callback function intended to be used to test for particular inputs on each VI, immediately after new + * inputs have been polled. + * + * This is useful for the rare cases where additional resolution is needed in the timings of player inputs, + * while the game is still updating comparatively slower. + * + * @param callback callback to run as soon as new inputs are obtained + * @param arg the argument to pass to the callback + * + * @see PadMgr_UnsetInputRetraceCallback + */ +void PadMgr_SetInputRetraceCallback(void (*callback)(void*), void* arg) { + sPadMgrInstance->inputRetraceCallback = callback; + sPadMgrInstance->inputRetraceArg = arg; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_Lock.s") +/** + * Unsets the input retrace callback if the provided function and argument are the same as those already registered. + * + * @param callback the callback to test against + * @param arg the argument to test against + * + * @see PadMgr_SetInputRetraceCallback + */ +void PadMgr_UnsetInputRetraceCallback(void (*callback)(void*), void* arg) { + if ((sPadMgrInstance->inputRetraceCallback == callback) && (sPadMgrInstance->inputRetraceArg == arg)) { + sPadMgrInstance->inputRetraceCallback = NULL; + sPadMgrInstance->inputRetraceArg = NULL; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_Unlock.s") +/** + * 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(void) { + OSMesgQueue* serialEventQueue; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_801750FC.s") + osRecvMesg(&sPadMgrInstance->serialLockQueue, (OSMesg*)&serialEventQueue, OS_MESG_BLOCK); + return serialEventQueue; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80175364.s") +/** + * Like `PadMgr_AcquireSerialEventQueue` but for Voice access. + * + * @see PadMgr_AcquireSerialEventQueue + * @see PadMgr_VoiceReleaseSerialEventQueue + */ +OSMesgQueue* PadMgr_VoiceAcquireSerialEventQueue(void) { + OSMesgQueue* serialEventQueue; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80175434.s") + osRecvMesg(&sPadMgrInstance->serialLockQueue, (OSMesg*)&serialEventQueue, OS_MESG_BLOCK); + return serialEventQueue; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_8017544C.s") +/** + * 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(OSMesgQueue* serialEventQueue) { + osSendMesg(&sPadMgrInstance->serialLockQueue, (OSMesg)serialEventQueue, OS_MESG_BLOCK); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/PadMgr_RumbleSet.s") +/** + * Like `PadMgr_ReleaseSerialEventQueue` but for Voice access. + * + * @see PadMgr_VoiceAcquireSerialEventQueue + */ +void PadMgr_VoiceReleaseSerialEventQueue(OSMesgQueue* serialEventQueue) { + osSendMesg(&sPadMgrInstance->serialLockQueue, (OSMesg)serialEventQueue, OS_MESG_BLOCK); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/PadMgr_ControllerHasRumblePak.s") +/** + * 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(void) { + osRecvMesg(&sPadMgrInstance->lockQueue, NULL, OS_MESG_BLOCK); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_CalcStickEdges.s") +/** + * 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(void) { + osSendMesg(&sPadMgrInstance->lockQueue, NULL, OS_MESG_BLOCK); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_ParseState.s") +/** + * 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(void) { + s32 i; + s32 ret; + OSMesgQueue* serialEventQueue = PadMgr_AcquireSerialEventQueue(); + s32 triedRumbleComm = false; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_801759BC.s") + for (i = 0; i < MAXCONTROLLERS; i++) { + if (sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NORMAL) { + // Check status for whether a controller pak is connected + if (sPadMgrInstance->padStatus[i].status & CONT_CARD_ON) { + if (sPadMgrInstance->pakType[i] == CONT_PAK_RUMBLE) { + if (sPadMgrInstance->rumbleEnable[i]) { + if (sPadMgrInstance->rumbleTimer[i] < 3) { + // Rumble pak start -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80175AE0.s") + if (osMotorStart(&sPadMgrInstance->rumblePfs[i]) != 0) { + // error + sPadMgrInstance->pakType[i] = CONT_PAK_NONE; + } else { + sPadMgrInstance->rumbleTimer[i] = 3; + } + triedRumbleComm = true; + } + } else { + if (sPadMgrInstance->rumbleTimer[i] != 0) { + // Rumble Pak stop -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_Update.s") + if (osMotorStop(&sPadMgrInstance->rumblePfs[i]) != 0) { + // error + sPadMgrInstance->pakType[i] = CONT_PAK_NONE; + } else { + sPadMgrInstance->rumbleTimer[i]--; + } + triedRumbleComm = true; + } + } + } + } else if (sPadMgrInstance->pakType[i] != CONT_PAK_NONE) { + sPadMgrInstance->pakType[i] = CONT_PAK_NONE; + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_Stop.s") + if (!triedRumbleComm) { + // 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 = sPadMgrRetraceCount % MAXCONTROLLERS; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/func_80175E68.s") + if ((sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NORMAL) && + (sPadMgrInstance->padStatus[i].status & CONT_CARD_ON) && (sPadMgrInstance->pakType[i] != CONT_PAK_RUMBLE)) { + ret = osMotorInit(serialEventQueue, &sPadMgrInstance->rumblePfs[i], i); -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_GetInput.s") + if (ret == 0) { + // Got rumble pak + sPadMgrInstance->pakType[i] = CONT_PAK_RUMBLE; + sPadMgrInstance->rumbleTimer[i] = 2; + } else if (ret == PFS_ERR_DEVICE) { + // Not a rumble pak + if (sPadMgrInstance->pakType[i] != CONT_PAK_OTHER) { + sPadMgrInstance->pakType[i] = CONT_PAK_OTHER; + } + } else if (ret == PFS_ERR_CONTRFAIL) { + // Pak communication error + } else if (ret == PFS_ERR_NOPACK) { + // No controller pak + } else { + // Unrecognized return code + Fault_AddHungupAndCrash("../padmgr.c", 594); + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_GetInput2.s") + PadMgr_ReleaseSerialEventQueue(serialEventQueue); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_ThreadEntry.s") +/** + * Immediately stops rumble on all controllers + */ +void PadMgr_RumbleStop(void) { + OSMesgQueue* serialEventQueue = PadMgr_AcquireSerialEventQueue(); + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/PadMgr_Init.s") + for (i = 0; i < MAXCONTROLLERS; i++) { + if ((sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NORMAL) && + (osMotorInit(serialEventQueue, &sPadMgrInstance->rumblePfs[i], i) == 0)) { + // If there is a rumble pak attached to this controller, stop it + osMotorStop(&sPadMgrInstance->rumblePfs[i]); + } + } + PadMgr_ReleaseSerialEventQueue(serialEventQueue); +} + +/** + * Prevents rumble for 12 VI, ~0.2 seconds at 60 VI/sec + */ +void PadMgr_RumblePause(void) { + sPadMgrInstance->rumbleOffTimer = 12; +} + +/** + * Enables or disables rumble on controller port `port` for 24 VI, + * ~0.4 seconds at 60 VI/sec and ~0.48 seconds at 50 VI/sec + */ +void PadMgr_RumbleSetSingle(s32 port, s32 enable) { + sPadMgrInstance->rumbleEnable[port] = enable; + sPadMgrInstance->rumbleOnTimer = 24; +} + +/** + * Enables or disables rumble on all controller ports for 24 VI, + * ~0.4 seconds at 60 VI/sec and ~0.48 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(u8 enable[MAXCONTROLLERS]) { + s32 i; + + for (i = 0; i < MAXCONTROLLERS; i++) { + sPadMgrInstance->rumbleEnable[i] = enable[i]; + } + sPadMgrInstance->rumbleOnTimer = 24; +} + +s32 PadMgr_ControllerHasRumblePak(s32 port) { + return sPadMgrInstance->pakType[port] == CONT_PAK_RUMBLE; +} + +void PadMgr_AdjustInput(Input* input) { + s32 plus; + s32 minus; + s32 pressX; + s32 pressX2; + s32 pressY; + s32 pressY2; + s32 pad1; + s32 pad2; + s32 pad3; + f32 pad4; + f32 newX; + f32 newY; + f32 magnitude; + f32 angle; + s8 curX = input->cur.stick_x; + s8 curY = input->cur.stick_y; + + if (CHECK_BTN_ANY(input->press.button, BTN_RESET) || (input->press.stick_x == 0)) { + input->press.stick_x = 61; + input->press.errno = -61; + input->press.stick_y = 63; + input->rel.errno = -63; + } + pressX = input->press.stick_x; + pressX2 = (s8)input->press.errno; + pressY = input->press.stick_y; + pressY2 = (s8)input->rel.errno; + + if (CHECK_BTN_ANY(input->cur.button, BTN_RESET)) { + minus = curX - 7; + plus = curX + 7; + + if (minus > 0) { + if (pressX < minus - 3) { + pressX = minus - 3; + input->press.stick_x = minus - 3; + } + } else if (plus < 0) { + if (pressX2 > plus + 3) { + pressX2 = plus + 3; + input->press.errno = plus + 3; + } + } + + minus = curY - 7; + plus = curY + 7; + + if (minus > 0) { + if (pressY < minus - 3) { + pressY = minus - 3; + input->press.stick_y = minus - 3; + } + } else if (plus < 0) { + if (pressY2 > plus + 3) { + pressY2 = plus + 3; + input->rel.errno = plus + 3; + } + } + } + + minus = curX - 7; + plus = curX + 7; + + if (minus > 0) { + newX = (pressX < minus) ? 1.0f : (f32)minus / pressX; + } else if (plus < 0) { + newX = (pressX2 > plus) ? -1.0f : -(f32)plus / pressX2; + } else { + newX = 0.0f; + } + + minus = curY - 7; + plus = curY + 7; + + if (minus > 0) { + newY = (pressY < minus) ? 1.0f : (f32)minus / pressY; + } else if (plus < 0) { + newY = (pressY2 > plus) ? -1.0f : -(f32)plus / pressY2; + } else { + newY = 0.0f; + } + + if (1) { + s32 pad; + + magnitude = sqrtf(SQ(newX) + SQ(newY)); + if (magnitude > 1.0f) { + magnitude = 1.0f; + } + angle = Math_Atan2F_XY(curY, -curX); + newX = -sinf(angle) * magnitude; + newY = cosf(angle) * magnitude; + } + input->rel.stick_x = newX * 60.5f; + input->rel.stick_y = newY * 60.5f; +} + +/** + * Updates `sPadMgrInstance->inputs` based on the error response of each controller + */ +void PadMgr_UpdateInputs(void) { + s32 diff; + Input* input = &sPadMgrInstance->inputs[0]; + s32 i; + OSContPad* pad = &sPadMgrInstance->pads[0]; + + for (i = 0; i < sPadMgrInstance->nControllers; i++, input++, pad++) { + s32 isStandardController; + + input->prev = input->cur; + isStandardController = sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NORMAL; + if (isStandardController) { + switch (pad->errno) { + case 0: + // No error, copy inputs + input->cur = *pad; + break; + + case CHNL_ERR_OVERRUN >> 4: + // Overrun error, reuse previous inputs + input->cur = input->prev; + break; + + 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 = pad->errno; + if (sPadMgrInstance->ctrlrType[i] != PADMGR_CONT_NONE) { + // If we get no response, consider the controller disconnected + sPadMgrInstance->ctrlrType[i] = PADMGR_CONT_NONE; + sPadMgrInstance->pakType[i] = CONT_PAK_NONE; + sPadMgrInstance->rumbleTimer[i] = 0xFF; + } + break; + + default: + // Unknown error response + Fault_AddHungupAndCrash("../padmgr.c", 1098); + break; + } + } else { + input->cur.button = 0; + input->cur.stick_x = 0; + input->cur.stick_y = 0; + input->cur.errno = pad->errno; + } + + // If opposed directions on the D-Pad are pressed at the same time, mask both out + if ((input->cur.button & (BTN_DDOWN | BTN_DUP)) == (BTN_DDOWN | BTN_DUP)) { + input->cur.button &= ~(BTN_DDOWN | BTN_DUP); + } + if ((input->cur.button & (BTN_DRIGHT | BTN_DLEFT)) == (BTN_DRIGHT | BTN_DLEFT)) { + input->cur.button &= ~(BTN_DRIGHT | BTN_DLEFT); + } + + // Calculate pressed and relative inputs + diff = input->prev.button ^ input->cur.button; + input->press.button |= (u16)(diff & input->cur.button); + input->rel.button |= (u16)(diff & input->prev.button); + + if (1) {} + PadMgr_AdjustInput(input); + } +} + +/** + * Looks for plugged in voice recognition units and initializes them. + * + * This runs only on startup, there will be no attempts to initialize + * a VRU other than on the first VI retrace. + */ +void PadMgr_InitVoice(void) { + s32 i; + OSMesgQueue* serialEventQueue; + s32 ret; + + for (i = 0; i < sPadMgrInstance->nControllers; i++) { + if (sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_VOICE_PLUGGED) { + serialEventQueue = PadMgr_AcquireSerialEventQueue(); + + ret = osVoiceInit(serialEventQueue, &gVoiceHandle, i); + + PadMgr_ReleaseSerialEventQueue(serialEventQueue); + + if (ret != 0) { + // error + } else { + sPadMgrInstance->ctrlrType[i] = PADMGR_CONT_VOICE; + sVoiceInitStatus = VOICE_INIT_SUCCESS; + func_801A4EB0(); + } + } + } + // If sVoiceInitStatus is still VOICE_INIT_TRY after the first attempt to initialize a VRU, don't try again + if (sVoiceInitStatus == VOICE_INIT_TRY) { + sVoiceInitStatus = VOICE_INIT_FAILED; + } +} + +/** + * Update the state of connected controllers + */ +void PadMgr_UpdateConnections(void) { + s32 ctrlrMask = 0; + s32 i; + char msg[50]; + + for (i = 0; i < MAXCONTROLLERS; i++) { + if (sPadMgrInstance->padStatus[i].errno == 0) { + switch (sPadMgrInstance->padStatus[i].type & CONT_TYPE_MASK) { + case CONT_TYPE_NORMAL: + // Standard N64 Controller + ctrlrMask |= (1 << i); + if (sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NONE) { + sPadMgrInstance->ctrlrType[i] = PADMGR_CONT_NORMAL; + } + break; + + case CONT_TYPE_MOUSE: + // N64 Mouse + if (sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NONE) { + sPadMgrInstance->ctrlrType[i] = PADMGR_CONT_MOUSE; + } + break; + + case CONT_TYPE_VOICE: + // Voice Recognition Unit + if (sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NONE) { + sPadMgrInstance->ctrlrType[i] = PADMGR_CONT_VOICE_PLUGGED; + sPadMgrInstance->pakType[i] = CONT_PAK_NONE; + } + break; + + default: + // Other/Unrecognized + if (sPadMgrInstance->ctrlrType[i] == PADMGR_CONT_NONE) { + sPadMgrInstance->ctrlrType[i] = PADMGR_CONT_UNK; + // "Recognized an unknown type of controller (%04x)" + sprintf(msg, "知らない種類のコントローラ(%04x)を認識しました", + sPadMgrInstance->padStatus[i].type); + } + // Missing break required for matching + } + } else if (sPadMgrInstance->ctrlrType[i] != PADMGR_CONT_NONE) { + // Plugged controller errored + sPadMgrInstance->ctrlrType[i] = PADMGR_CONT_NONE; + sPadMgrInstance->pakType[i] = CONT_PAK_NONE; + sPadMgrInstance->rumbleTimer[i] = 0xFF; + } + } + sPadMgrInstance->validCtrlrsMask = ctrlrMask; +} + +void PadMgr_HandleRetrace(void) { + OSMesgQueue* serialEventQueue = PadMgr_AcquireSerialEventQueue(); + + // Begin reading controller data + osContStartReadData(serialEventQueue); + + // Execute rumble callback + if (sPadMgrInstance->rumbleRetraceCallback != NULL) { + sPadMgrInstance->rumbleRetraceCallback(sPadMgrInstance->rumbleRetraceArg); + } + + // Wait for controller data + osRecvMesg(serialEventQueue, NULL, OS_MESG_BLOCK); + osContGetReadData(sPadMgrInstance->pads); + + // Clear all but controller 1 + bzero(&sPadMgrInstance->pads[1], sizeof(*sPadMgrInstance->pads) * (MAXCONTROLLERS - 1)); + + // If in PreNMI, clear all controllers + if (sPadMgrInstance->isResetting) { + bzero(sPadMgrInstance->pads, sizeof(sPadMgrInstance->pads)); + } + + // Query controller statuses + osContStartQuery(serialEventQueue); + osRecvMesg(serialEventQueue, NULL, OS_MESG_BLOCK); + osContGetQuery(sPadMgrInstance->padStatus); + + // Lock serial message queue + PadMgr_ReleaseSerialEventQueue(serialEventQueue); + + // Update connections + PadMgr_UpdateConnections(); + + // Lock input data + PadMgr_LockPadData(); + + // Update input data + PadMgr_UpdateInputs(); + + // Execute input callback + if (sPadMgrInstance->inputRetraceCallback != NULL) { + sPadMgrInstance->inputRetraceCallback(sPadMgrInstance->inputRetraceArg); + } + + // Unlock input data + PadMgr_UnlockPadData(); + + // Try and initialize a Voice Recognition Unit if not already attempted + if (sVoiceInitStatus != VOICE_INIT_FAILED) { + PadMgr_InitVoice(); + } + + // Rumble Pak + if (gFaultStruct.msgId != 0) { + // If fault is active, no rumble + PadMgr_RumbleStop(); + } else if (sPadMgrInstance->rumbleOffTimer > 0) { + // If the rumble off timer is active, no rumble + --sPadMgrInstance->rumbleOffTimer; + PadMgr_RumbleStop(); + } else if (sPadMgrInstance->rumbleOnTimer == 0) { + // If the rumble on timer is inactive, no rumble + PadMgr_RumbleStop(); + } else if (!sPadMgrInstance->isResetting) { + // If not resetting, update rumble + PadMgr_UpdateRumble(); + --sPadMgrInstance->rumbleOnTimer; + } + + sPadMgrRetraceCount++; +} + +void PadMgr_HandlePreNMI(void) { + sPadMgrInstance->isResetting = true; + PadMgr_RumblePause(); +} + +/** + * Fetches the most recently polled inputs from padmgr. + * + * NOTE: This function does not lock the inputs while reading them. + * The padmgr thread may interrupt this function and poll new inputs while the thread running this function is + * currently copying the old inputs potentially resulting in a mix of newly polled and old inputs being used. + * It is preferable to use `PadMgr_GetInput` or `PadMgr_GetInput2`. + * + * @param inputs Array of Input of length MAXCONTROLLERS to copy inputs into + * @param gameRequest True if polling inputs for updating the game state + */ +void PadMgr_GetInputNoLock(Input* inputs, s32 gameRequest) { + s32 i; + Input* input = &sPadMgrInstance->inputs[0]; + Input* inputOut = &inputs[0]; + s32 buttonDiff; + + for (i = 0; i < MAXCONTROLLERS; i++) { + if (gameRequest) { + // Copy inputs as-is, press and rel are calculated prior in `PadMgr_UpdateInputs` + *inputOut = *input; + // Zero parts of the press and rel inputs in the polled inputs so they are not read more than once + input->press.button = 0; + input->rel.button = 0; + } else { + // 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 = input->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); + } + input++; + inputOut++; + } +} + +/** + * Fetches the most recently polled inputs from padmgr. + * + * @param inputs Array of Input of length MAXCONTROLLERS to copy inputs into + * @param gameRequest True if polling inputs for updating the game state + */ +void PadMgr_GetInput(Input* inputs, s32 gameRequest) { + PadMgr_LockPadData(); + PadMgr_GetInputNoLock(inputs, gameRequest); + PadMgr_UnlockPadData(); +} + +/** + * Copy of `PadMgr_GetInput` + * + * @see PadMgr_GetInput + */ +void PadMgr_GetInput2(Input* inputs, s32 gameRequest) { + PadMgr_LockPadData(); + PadMgr_GetInputNoLock(inputs, gameRequest); + PadMgr_UnlockPadData(); +} + +void PadMgr_ThreadEntry() { + s16* interruptMsg = NULL; + s32 actionBits; + s32 exit; + + osCreateMesgQueue(&sPadMgrInstance->interruptQueue, sPadMgrInstance->interruptMsgBuf, + ARRAY_COUNT(sPadMgrInstance->interruptMsgBuf)); + IrqMgr_AddClient(sPadMgrInstance->irqMgr, &sPadMgrInstance->irqClient, &sPadMgrInstance->interruptQueue); + + actionBits = 0; + exit = false; + + while (!exit) { + // Process all messages currently in the queue, instead of only a single mssage. + // Deduplicates the same message. + do { + osRecvMesg(&sPadMgrInstance->interruptQueue, (OSMesg*)&interruptMsg, OS_MESG_BLOCK); + switch (*interruptMsg) { + case OS_SC_RETRACE_MSG: + actionBits |= PADMGR_RETRACE_MSG; + break; + + case OS_SC_PRE_NMI_MSG: + actionBits |= PADMGR_PRE_NMI_MSG; + break; + + case OS_SC_NMI_MSG: + actionBits |= PADMGR_NMI_MSG; + break; + } + } while (!MQ_IS_EMPTY(&sPadMgrInstance->interruptQueue)); + + // Act on received messages + while (actionBits != 0) { + if (actionBits & PADMGR_NMI_MSG) { + actionBits &= ~PADMGR_NMI_MSG; + exit = true; + } else if (actionBits & PADMGR_PRE_NMI_MSG) { + actionBits &= ~PADMGR_PRE_NMI_MSG; + PadMgr_HandlePreNMI(); + } else if (actionBits & PADMGR_RETRACE_MSG) { + actionBits &= ~PADMGR_RETRACE_MSG; + PadMgr_HandleRetrace(); + } + } + } + + IrqMgr_RemoveClient(sPadMgrInstance->irqMgr, &sPadMgrInstance->irqClient); +} + +void PadMgr_Init(OSMesgQueue* siEvtQ, IrqMgr* irqMgr, OSId threadId, OSPri pri, void* stack) { + bzero(sPadMgrInstance, sizeof(PadMgr)); + sPadMgrInstance->irqMgr = irqMgr; + + // These are unique access tokens, there should only ever be room for one OSMesg in these queues + osCreateMesgQueue(&sPadMgrInstance->serialLockQueue, &sPadMgrInstance->serialMsg, 1); + osCreateMesgQueue(&sPadMgrInstance->lockQueue, &sPadMgrInstance->lockMsg, 1); + + PadMgr_UnlockPadData(); + PadSetup_Init(siEvtQ, &sPadMgrInstance->validCtrlrsMask, sPadMgrInstance->padStatus); + sPadMgrInstance->nControllers = MAXCONTROLLERS; + osContSetCh(sPadMgrInstance->nControllers); + PadMgr_ReleaseSerialEventQueue(siEvtQ); + + osCreateThread(&sPadMgrInstance->thread, threadId, PadMgr_ThreadEntry, sPadMgrInstance, stack, pri); + osStartThread(&sPadMgrInstance->thread); +} diff --git a/src/code/sys_rumble.c b/src/code/sys_rumble.c index 4101758be0..06bef6e349 100644 --- a/src/code/sys_rumble.c +++ b/src/code/sys_rumble.c @@ -24,12 +24,12 @@ void RumbleManager_Update(RumbleManager* rumbleMgr) { if (D_801D1E70) { for (i = 0; i < MAXCONTROLLERS; i++) { - func_8017544C(i, false); + PadMgr_RumbleSetSingle(i, false); } } D_801D1E70 = rumbleMgr->updateEnabled; - func_80175434(); + PadMgr_RumblePause(); return; } @@ -39,7 +39,7 @@ void RumbleManager_Update(RumbleManager* rumbleMgr) { // Start up the manager by wiping old requests if (rumbleMgr->state == RUMBLEMANAGER_STATE_INITIAL) { for (i = 0; i < MAXCONTROLLERS; i++) { - func_8017544C(i, false); + PadMgr_RumbleSetSingle(i, false); } for (i = 0; i < RUMBLE_REQUEST_BUFFER_SIZE; i++) { @@ -59,7 +59,7 @@ void RumbleManager_Update(RumbleManager* rumbleMgr) { rumbleMgr->state = RUMBLEMANAGER_STATE_RUNNING; - func_80175434(); + PadMgr_RumblePause(); } if (rumbleMgr->state != RUMBLEMANAGER_STATE_WIPE) { @@ -146,7 +146,7 @@ void RumbleManager_Update(RumbleManager* rumbleMgr) { rumbleMgr->overrideDecayStep = 0; rumbleMgr->overrideAccumulator = 0; - func_80175434(); + PadMgr_RumblePause(); } } diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c index 41441f3a28..fe4ca5ef83 100644 --- a/src/code/z_parameter.c +++ b/src/code/z_parameter.c @@ -29,7 +29,7 @@ typedef struct { /* 0x03 */ u8 flags3; } RestrictionFlags; -Input sPostmanTimerInput[4]; +Input sPostmanTimerInput[MAXCONTROLLERS]; #define RESTRICTIONS_TABLE_END 0xFF @@ -887,10 +887,10 @@ void Interface_SetVertices(PlayState* play) { s32 sPostmanTimerInputBtnAPressed = false; -void Interface_PostmanTimerCallback(s32 arg0) { +void Interface_PostmanTimerCallback(void* arg) { s32 btnAPressed; - func_80175E68(&sPostmanTimerInput[0], 0); + PadMgr_GetInputNoLock(sPostmanTimerInput, false); btnAPressed = CHECK_BTN_ALL(sPostmanTimerInput[0].cur.button, BTN_A); if ((btnAPressed != sPostmanTimerInputBtnAPressed) && btnAPressed) { gSaveContext.postmanTimerStopOsTime = osGetTime(); @@ -5654,7 +5654,7 @@ void Interface_DrawTimers(PlayState* play) { } gSaveContext.timerStates[TIMER_ID_POSTMAN] = TIMER_STATE_POSTMAN_COUNTING; sPostmanTimerInputBtnAPressed = true; - func_80174F7C(Interface_PostmanTimerCallback, NULL); + PadMgr_SetInputRetraceCallback(Interface_PostmanTimerCallback, NULL); break; case TIMER_STATE_POSTMAN_STOP: @@ -5663,7 +5663,7 @@ void Interface_DrawTimers(PlayState* play) { postmanTimerStopOsTime - ((void)0, gSaveContext.timerStartOsTimes[TIMER_ID_POSTMAN]) - ((void)0, gSaveContext.timerPausedOsTimes[TIMER_ID_POSTMAN])); gSaveContext.timerStates[TIMER_ID_POSTMAN] = TIMER_STATE_POSTMAN_END; - func_80174F9C(Interface_PostmanTimerCallback, NULL); + PadMgr_UnsetInputRetraceCallback(Interface_PostmanTimerCallback, NULL); break; case TIMER_STATE_POSTMAN_COUNTING: @@ -7211,7 +7211,7 @@ void Interface_Update(PlayState* play) { void Interface_Destroy(PlayState* play) { Map_Destroy(play); - func_80174F9C(Interface_PostmanTimerCallback, NULL); + PadMgr_UnsetInputRetraceCallback(Interface_PostmanTimerCallback, NULL); } void Interface_Init(PlayState* play) { diff --git a/src/code/z_rumble.c b/src/code/z_rumble.c index ce5cc16b40..3cca1d4325 100644 --- a/src/code/z_rumble.c +++ b/src/code/z_rumble.c @@ -68,11 +68,11 @@ void Rumble_Request(f32 distSq, u8 sourceIntensity, u8 decayTimer, u8 decayStep) void Rumble_Init(void) { RumbleManager_Init(&gRumbleMgr); - func_80174F24(Rumble_Update, NULL); + PadMgr_SetRumbleRetraceCallback(Rumble_Update, NULL); } void Rumble_Destroy(void) { - func_80174F44(Rumble_Update, NULL); + PadMgr_UnsetRumbleRetraceCallback(Rumble_Update, NULL); RumbleManager_Destroy(&gRumbleMgr); } diff --git a/src/libultra/io/motor.c b/src/libultra/io/motor.c index 649a8b368f..9e0eb127ee 100644 --- a/src/libultra/io/motor.c +++ b/src/libultra/io/motor.c @@ -6,40 +6,40 @@ #define BANK_ADDR 0x400 #define MOTOR_ID 0x80 -OSPifRam osPifBuffers[MAXCONTROLLERS]; +OSPifRam __MotorDataBuf[MAXCONTROLLERS]; s32 __osPfsSelectBank(OSPfs* pfs, u8 bank); -s32 __osMotorAccess(OSPfs* pfs, u32 vibrate) { +s32 __osMotorAccess(OSPfs* pfs, s32 flag) { s32 i; s32 ret; - u8* buf = (u8*)&osPifBuffers[pfs->channel]; + u8* ptr = (u8*)&__MotorDataBuf[pfs->channel]; - if (!(pfs->status & 8)) { - return 5; + if (!(pfs->status & PFS_MOTOR_INITIALIZED)) { + return PFS_ERR_INVALID; } __osSiGetAccess(); - osPifBuffers[pfs->channel].status = 1; - buf += pfs->channel; + __MotorDataBuf[pfs->channel].status = CONT_CMD_EXE; + ptr += pfs->channel; for (i = 0; i < BLOCKSIZE; i++) { - ((__OSContRamReadFormat*)buf)->data[i] = vibrate; + READFORMAT(ptr)->data[i] = flag; } __osContLastPoll = CONT_CMD_END; - __osSiRawStartDma(OS_WRITE, &osPifBuffers[pfs->channel]); + __osSiRawStartDma(OS_WRITE, &__MotorDataBuf[pfs->channel]); osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK); - __osSiRawStartDma(OS_READ, &osPifBuffers[pfs->channel]); + __osSiRawStartDma(OS_READ, &__MotorDataBuf[pfs->channel]); osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK); - ret = ((__OSContRamReadFormat*)buf)->rxsize & 0xC0; + ret = READFORMAT(ptr)->rxsize & CHNL_ERR_MASK; if (!ret) { - if (!vibrate) { - if (((__OSContRamReadFormat*)buf)->datacrc != 0) { + if (!flag) { + if (READFORMAT(ptr)->datacrc != 0) { ret = PFS_ERR_CONTRFAIL; } } else { - if (((__OSContRamReadFormat*)buf)->datacrc != 0xEB) { + if (READFORMAT(ptr)->datacrc != 0xEB) { ret = PFS_ERR_CONTRFAIL; } } @@ -50,76 +50,75 @@ s32 __osMotorAccess(OSPfs* pfs, u32 vibrate) { return ret; } -void _MakeMotorData(s32 channel, OSPifRam* buf) { - u8* bufptr = (u8*)buf; - __OSContRamReadFormat mempakwr; +void _MakeMotorData(s32 channel, OSPifRam* mdata) { + u8* ptr = (u8*)mdata->ramarray; + __OSContRamReadFormat ramreadformat; s32 i; - mempakwr.dummy = 0xFF; - mempakwr.txsize = 0x23; - mempakwr.rxsize = 1; - mempakwr.cmd = 3; // write mempak - mempakwr.hi = 0x600 >> 3; - mempakwr.lo = (u8)(__osContAddressCrc(0x600) | (0x600 << 5)); + ramreadformat.dummy = CONT_CMD_NOP; + ramreadformat.txsize = CONT_CMD_WRITE_PAK_TX; + ramreadformat.rxsize = CONT_CMD_WRITE_PAK_RX; + ramreadformat.cmd = CONT_CMD_WRITE_PAK; + ramreadformat.hi = CONT_BLOCK_RUMBLE >> 3; + ramreadformat.lo = (u8)(__osContAddressCrc(CONT_BLOCK_RUMBLE) | (CONT_BLOCK_RUMBLE << 5)); if (channel != 0) { for (i = 0; i < channel; i++) { - *bufptr++ = 0; + *ptr++ = 0; } } - *(__OSContRamReadFormat*)bufptr = mempakwr; - bufptr += sizeof(mempakwr); - *bufptr = 0xFE; + *READFORMAT(ptr) = ramreadformat; + ptr += sizeof(ramreadformat); + *ptr = CONT_CMD_END; } -s32 osMotorInit(OSMesgQueue* ctrlrqueue, OSPfs* pfs, s32 channel) { +s32 osMotorInit(OSMesgQueue* mq, OSPfs* pfs, s32 channel) { s32 ret; - u8 sp24[BLOCKSIZE]; + u8 temp[BLOCKSIZE]; - pfs->queue = ctrlrqueue; + pfs->queue = mq; pfs->channel = channel; pfs->activebank = 0xFF; pfs->status = 0; ret = __osPfsSelectBank(pfs, 0xFE); - if (ret == 2) { + if (ret == PFS_ERR_NEW_PACK) { ret = __osPfsSelectBank(pfs, MOTOR_ID); } if (ret != 0) { return ret; } - ret = __osContRamRead(ctrlrqueue, channel, 0x400, sp24); - if (ret == 2) { - ret = 4; // "Controller pack communication error" + ret = __osContRamRead(mq, channel, CONT_BLOCK_DETECT, temp); + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; } if (ret != 0) { return ret; } - if (sp24[BLOCKSIZE - 1] == 0xFE) { - return 0xB; + if (temp[BLOCKSIZE - 1] == 0xFE) { + return PFS_ERR_DEVICE; } ret = __osPfsSelectBank(pfs, MOTOR_ID); if (ret == 2) { - ret = 4; // "Controller pack communication error" + ret = PFS_ERR_CONTRFAIL; } if (ret != 0) { return ret; } - ret = __osContRamRead(ctrlrqueue, channel, BANK_ADDR, sp24); - if (ret == 2) { - ret = 4; // "Controller pack communication error" + ret = __osContRamRead(mq, channel, BANK_ADDR, temp); + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; } if (ret != 0) { return ret; } - if (sp24[BLOCKSIZE - 1] != MOTOR_ID) { - return 0xB; + if (temp[BLOCKSIZE - 1] != MOTOR_ID) { + return PFS_ERR_DEVICE; } if (!(pfs->status & PFS_MOTOR_INITIALIZED)) { - _MakeMotorData(channel, &osPifBuffers[channel]); + _MakeMotorData(channel, &__MotorDataBuf[channel]); } pfs->status = PFS_MOTOR_INITIALIZED; - - return 0; // "Recognized rumble pak" + return 0; } diff --git a/src/overlays/gamestates/ovl_title/z_title.c b/src/overlays/gamestates/ovl_title/z_title.c index 01e29668e8..59b1bed02d 100644 --- a/src/overlays/gamestates/ovl_title/z_title.c +++ b/src/overlays/gamestates/ovl_title/z_title.c @@ -165,7 +165,7 @@ void ConsoleLogo_Init(GameState* thisx) { this->state.destroy = ConsoleLogo_Destroy; this->exit = false; - if (!(Padmgr_GetControllerBitmask() & 1)) { + if (!(PadMgr_GetValidControllersMask() & 1)) { gSaveContext.fileNum = 0xFEDC; } else { gSaveContext.fileNum = 0xFF; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index c3c12979b1..6d9916fd76 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -3164,33 +3164,33 @@ 0x80174B20:("ListAlloc_Free",), 0x80174BA0:("ListAlloc_FreeAll",), 0x80174BF0:("Main",), - 0x80174F10:("Padmgr_GetControllerBitmask",), - 0x80174F24:("func_80174F24",), - 0x80174F44:("func_80174F44",), - 0x80174F7C:("func_80174F7C",), - 0x80174F9C:("func_80174F9C",), - 0x80174FD4:("Padmgr_GetEventCallback",), - 0x80175008:("func_80175008",), - 0x8017503C:("Padmgr_SetEventCallback",), - 0x8017506C:("func_8017506C",), - 0x8017509C:("Padmgr_Lock",), - 0x801750CC:("Padmgr_Unlock",), - 0x801750FC:("func_801750FC",), - 0x80175364:("func_80175364",), - 0x80175434:("func_80175434",), - 0x8017544C:("func_8017544C",), + 0x80174F10:("PadMgr_GetValidControllersMask",), + 0x80174F24:("PadMgr_SetRumbleRetraceCallback",), + 0x80174F44:("PadMgr_UnsetRumbleRetraceCallback",), + 0x80174F7C:("PadMgr_SetInputRetraceCallback",), + 0x80174F9C:("PadMgr_UnsetInputRetraceCallback",), + 0x80174FD4:("PadMgr_AcquireSerialEventQueue",), + 0x80175008:("PadMgr_VoiceAcquireSerialEventQueue",), + 0x8017503C:("PadMgr_ReleaseSerialEventQueue",), + 0x8017506C:("PadMgr_VoiceReleaseSerialEventQueue",), + 0x8017509C:("PadMgr_LockPadData",), + 0x801750CC:("PadMgr_UnlockPadData",), + 0x801750FC:("PadMgr_UpdateRumble",), + 0x80175364:("PadMgr_RumbleStop",), + 0x80175434:("PadMgr_RumblePause",), + 0x8017544C:("PadMgr_RumbleSetSingle",), 0x80175474:("PadMgr_RumbleSet",), 0x801754C0:("PadMgr_ControllerHasRumblePak",), - 0x801754E0:("Padmgr_CalcStickEdges",), - 0x801757A4:("Padmgr_ParseState",), - 0x801759BC:("func_801759BC",), - 0x80175AE0:("func_80175AE0",), - 0x80175C80:("Padmgr_Update",), - 0x80175E3C:("Padmgr_Stop",), - 0x80175E68:("func_80175E68",), - 0x80175F98:("Padmgr_GetInput",), - 0x80175FD4:("Padmgr_GetInput2",), - 0x80176010:("Padmgr_ThreadEntry",), + 0x801754E0:("PadMgr_AdjustInput",), + 0x801757A4:("PadMgr_UpdateInputs",), + 0x801759BC:("PadMgr_InitVoice",), + 0x80175AE0:("PadMgr_UpdateConnections",), + 0x80175C80:("PadMgr_HandleRetrace",), + 0x80175E3C:("PadMgr_HandlePreNMI",), + 0x80175E68:("PadMgr_GetInputNoLock",), + 0x80175F98:("PadMgr_GetInput",), + 0x80175FD4:("PadMgr_GetInput2",), + 0x80176010:("PadMgr_ThreadEntry",), 0x80176194:("PadMgr_Init",), 0x80176280:("Sched_SwapFramebuffer",), 0x80176314:("Sched_RetraceUpdateFramebuffer",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index b69ab2ff48..f40abb468f 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -328,7 +328,7 @@ 0x8009CD50:("sRandFloat","f32","",0x4), 0x8009CD60:("sArenaLockMsg","OSMesg","[1]",0x4), 0x8009CD70:("tmp_task","OSTask","",0x40), - 0x8009CDB0:("osPifBuffers","OSPifRam","[4]",0x100), + 0x8009CDB0:("__MotorDataBuf","OSPifRam","[4]",0x100), 0x8009CEB0:("siAccessBuf","OSMesg","[1]",0x4), 0x8009CEB8:("__osSiAccessQueue","OSMesgQueue","",0x18), 0x8009CED0:("__osContPifRam","OSPifRam","",0x40), @@ -2180,9 +2180,9 @@ 0x801D1520:("gScreenWidth","s32","",0x4), 0x801D1524:("gScreenHeight","s32","",0x4), 0x801D1528:("startHeapSize","UNK_TYPE4","",0x4), - 0x801D1530:("padmgrContext","PadMgr*","",0x4), - 0x801D1534:("controllerInputsCaptured","UNK_TYPE4","",0x4), - 0x801D1538:("D_801D1538","UNK_TYPE4","",0x4), + 0x801D1530:("sPadMgrInstance","PadMgr*","",0x4), + 0x801D1534:("sPadMgrRetraceCount","UNK_TYPE4","",0x4), + 0x801D1538:("sVoiceInitStatus","UNK_TYPE4","",0x4), 0x801D1540:("D_801D1540","UNK_PTR","",0x4), 0x801D1570:("D_801D1570","f32","[13]",0x34), 0x801D15B0:("gZeroVec3f","Vec3f","",0xC), @@ -4292,7 +4292,7 @@ 0x801FD598:("sCustomSequencePc","UNK_TYPE1","",0x1), 0x801FD5A0:("D_801FD5A0","UNK_TYPE1","",0x1), 0x801FD5A4:("D_801FD5A4","UNK_TYPE1","",0x1), - 0x801FD5B8:("D_801FD5B8","UNK_TYPE1","",0x1), + 0x801FD5B8:("gVoiceHandle","UNK_TYPE1","",0x1), 0x801FD5C4:("D_801FD5C4","UNK_TYPE1","",0x1), 0x801FD5C8:("D_801FD5C8","UNK_TYPE1","",0x1), 0x801FD5E8:("D_801FD5E8","UNK_TYPE1","",0x1), diff --git a/tools/namefixer.py b/tools/namefixer.py index a0aa4b315b..a3fbddec90 100755 --- a/tools/namefixer.py +++ b/tools/namefixer.py @@ -742,6 +742,28 @@ wordReplace = { "func_80102544": "LightContext_SetFog", + "Padmgr_GetControllerBitmask": "PadMgr_GetValidControllersMask", + "func_80174F24": "PadMgr_SetRumbleRetraceCallback", + "func_80174F44": "PadMgr_UnsetRumbleRetraceCallback", + "func_80174F7C": "PadMgr_SetInputRetraceCallback", + "func_80174F9C": "PadMgr_UnsetInputRetraceCallback", + "Padmgr_GetEventCallback": "PadMgr_AcquireSerialEventQueue", + "func_80175008": "PadMgr_VoiceAcquireSerialEventQueue", + "Padmgr_SetEventCallback": "PadMgr_ReleaseSerialEventQueue", + "func_8017506C": "PadMgr_VoiceReleaseSerialEventQueue", + "Padmgr_Lock": "PadMgr_LockPadData", + "Padmgr_Unlock": "PadMgr_UnlockPadData", + "func_801750FC": "PadMgr_UpdateRumble", + "func_80175364": "PadMgr_RumbleStop", + "func_80175434": "PadMgr_RumblePause", + "func_8017544C": "PadMgr_RumbleSetSingle", + "Padmgr_ParseState": "PadMgr_UpdateInputs", + "func_801759BC": "PadMgr_InitVoice", + "func_80175AE0": "PadMgr_UpdateConnections", + "Padmgr_Update": "PadMgr_HandleRetrace", + "Padmgr_Stop": "PadMgr_HandlePreNMI", + "func_80175E68": "PadMgr_GetInputNoLock", + # Structs "ActorAnimationEntry": "AnimationInfo", "ActorAnimationEntryS": "AnimationInfoS", diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index d6821e4aa0..ba751f02ad 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -2678,33 +2678,33 @@ asm/non_matchings/code/listalloc/func_80174AB4.s,func_80174AB4,0x80174AB4,0x1B asm/non_matchings/code/listalloc/func_80174B20.s,func_80174B20,0x80174B20,0x20 asm/non_matchings/code/listalloc/func_80174BA0.s,func_80174BA0,0x80174BA0,0x14 asm/non_matchings/code/main/main.s,main,0x80174BF0,0xC8 -asm/non_matchings/code/padmgr/Padmgr_GetControllerBitmask.s,Padmgr_GetControllerBitmask,0x80174F10,0x5 -asm/non_matchings/code/padmgr/func_80174F24.s,func_80174F24,0x80174F24,0x8 -asm/non_matchings/code/padmgr/func_80174F44.s,func_80174F44,0x80174F44,0xE -asm/non_matchings/code/padmgr/func_80174F7C.s,func_80174F7C,0x80174F7C,0x8 -asm/non_matchings/code/padmgr/func_80174F9C.s,func_80174F9C,0x80174F9C,0xE -asm/non_matchings/code/padmgr/Padmgr_GetEventCallback.s,Padmgr_GetEventCallback,0x80174FD4,0xD -asm/non_matchings/code/padmgr/func_80175008.s,func_80175008,0x80175008,0xD -asm/non_matchings/code/padmgr/Padmgr_SetEventCallback.s,Padmgr_SetEventCallback,0x8017503C,0xC -asm/non_matchings/code/padmgr/func_8017506C.s,func_8017506C,0x8017506C,0xC -asm/non_matchings/code/padmgr/Padmgr_Lock.s,Padmgr_Lock,0x8017509C,0xC -asm/non_matchings/code/padmgr/Padmgr_Unlock.s,Padmgr_Unlock,0x801750CC,0xC -asm/non_matchings/code/padmgr/func_801750FC.s,func_801750FC,0x801750FC,0x9A -asm/non_matchings/code/padmgr/func_80175364.s,func_80175364,0x80175364,0x34 -asm/non_matchings/code/padmgr/func_80175434.s,func_80175434,0x80175434,0x6 -asm/non_matchings/code/padmgr/func_8017544C.s,func_8017544C,0x8017544C,0xA +asm/non_matchings/code/padmgr/PadMgr_GetValidControllersMask.s,PadMgr_GetValidControllersMask,0x80174F10,0x5 +asm/non_matchings/code/padmgr/PadMgr_SetRumbleRetraceCallback.s,PadMgr_SetRumbleRetraceCallback,0x80174F24,0x8 +asm/non_matchings/code/padmgr/PadMgr_UnsetRumbleRetraceCallback.s,PadMgr_UnsetRumbleRetraceCallback,0x80174F44,0xE +asm/non_matchings/code/padmgr/PadMgr_SetInputRetraceCallback.s,PadMgr_SetInputRetraceCallback,0x80174F7C,0x8 +asm/non_matchings/code/padmgr/PadMgr_UnsetInputRetraceCallback.s,PadMgr_UnsetInputRetraceCallback,0x80174F9C,0xE +asm/non_matchings/code/padmgr/PadMgr_AcquireSerialEventQueue.s,PadMgr_AcquireSerialEventQueue,0x80174FD4,0xD +asm/non_matchings/code/padmgr/PadMgr_VoiceAcquireSerialEventQueue.s,PadMgr_VoiceAcquireSerialEventQueue,0x80175008,0xD +asm/non_matchings/code/padmgr/PadMgr_ReleaseSerialEventQueue.s,PadMgr_ReleaseSerialEventQueue,0x8017503C,0xC +asm/non_matchings/code/padmgr/PadMgr_VoiceReleaseSerialEventQueue.s,PadMgr_VoiceReleaseSerialEventQueue,0x8017506C,0xC +asm/non_matchings/code/padmgr/PadMgr_LockPadData.s,PadMgr_LockPadData,0x8017509C,0xC +asm/non_matchings/code/padmgr/PadMgr_UnlockPadData.s,PadMgr_UnlockPadData,0x801750CC,0xC +asm/non_matchings/code/padmgr/PadMgr_UpdateRumble.s,PadMgr_UpdateRumble,0x801750FC,0x9A +asm/non_matchings/code/padmgr/PadMgr_RumbleStop.s,PadMgr_RumbleStop,0x80175364,0x34 +asm/non_matchings/code/padmgr/PadMgr_RumblePause.s,PadMgr_RumblePause,0x80175434,0x6 +asm/non_matchings/code/padmgr/PadMgr_RumbleSetSingle.s,PadMgr_RumbleSetSingle,0x8017544C,0xA asm/non_matchings/code/padmgr/PadMgr_RumbleSet.s,PadMgr_RumbleSet,0x80175474,0x13 asm/non_matchings/code/padmgr/PadMgr_ControllerHasRumblePak.s,PadMgr_ControllerHasRumblePak,0x801754C0,0x8 -asm/non_matchings/code/padmgr/Padmgr_CalcStickEdges.s,Padmgr_CalcStickEdges,0x801754E0,0xB1 -asm/non_matchings/code/padmgr/Padmgr_ParseState.s,Padmgr_ParseState,0x801757A4,0x86 -asm/non_matchings/code/padmgr/func_801759BC.s,func_801759BC,0x801759BC,0x49 -asm/non_matchings/code/padmgr/func_80175AE0.s,func_80175AE0,0x80175AE0,0x68 -asm/non_matchings/code/padmgr/Padmgr_Update.s,Padmgr_Update,0x80175C80,0x6F -asm/non_matchings/code/padmgr/Padmgr_Stop.s,Padmgr_Stop,0x80175E3C,0xB -asm/non_matchings/code/padmgr/func_80175E68.s,func_80175E68,0x80175E68,0x4C -asm/non_matchings/code/padmgr/Padmgr_GetInput.s,Padmgr_GetInput,0x80175F98,0xF -asm/non_matchings/code/padmgr/Padmgr_GetInput2.s,Padmgr_GetInput2,0x80175FD4,0xF -asm/non_matchings/code/padmgr/Padmgr_ThreadEntry.s,Padmgr_ThreadEntry,0x80176010,0x61 +asm/non_matchings/code/padmgr/PadMgr_AdjustInput.s,PadMgr_AdjustInput,0x801754E0,0xB1 +asm/non_matchings/code/padmgr/PadMgr_UpdateInputs.s,PadMgr_UpdateInputs,0x801757A4,0x86 +asm/non_matchings/code/padmgr/PadMgr_InitVoice.s,PadMgr_InitVoice,0x801759BC,0x49 +asm/non_matchings/code/padmgr/PadMgr_UpdateConnections.s,PadMgr_UpdateConnections,0x80175AE0,0x68 +asm/non_matchings/code/padmgr/PadMgr_HandleRetrace.s,PadMgr_HandleRetrace,0x80175C80,0x6F +asm/non_matchings/code/padmgr/PadMgr_HandlePreNMI.s,PadMgr_HandlePreNMI,0x80175E3C,0xB +asm/non_matchings/code/padmgr/PadMgr_GetInputNoLock.s,PadMgr_GetInputNoLock,0x80175E68,0x4C +asm/non_matchings/code/padmgr/PadMgr_GetInput.s,PadMgr_GetInput,0x80175F98,0xF +asm/non_matchings/code/padmgr/PadMgr_GetInput2.s,PadMgr_GetInput2,0x80175FD4,0xF +asm/non_matchings/code/padmgr/PadMgr_ThreadEntry.s,PadMgr_ThreadEntry,0x80176010,0x61 asm/non_matchings/code/padmgr/PadMgr_Init.s,PadMgr_Init,0x80176194,0x3B asm/non_matchings/code/sched/Sched_SwapFramebuffer.s,Sched_SwapFramebuffer,0x80176280,0x25 asm/non_matchings/code/sched/Sched_RetraceUpdateFramebuffer.s,Sched_RetraceUpdateFramebuffer,0x80176314,0x14