Decompile padmgr.c (#1246)

* Decompile padmgr.c

* Format

* Enum names

* Update namefixer

* Suggested changes

Co-authored-by: Anghelo Carvajal <angheloalf95@gmail.com>

* Suggested changes, improve motor.c

Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>

* Further suggested changes

* Format

* Fix `controller.h` comment

Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com>

---------

Co-authored-by: Anghelo Carvajal <angheloalf95@gmail.com>
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com>
This commit is contained in:
Tharo 2023-05-26 18:57:44 +01:00 committed by GitHub
parent 22af2bb8fe
commit 6d20839ab0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1103 additions and 236 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;

97
include/padmgr.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

1
spec
View File

@ -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"

View File

@ -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;

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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",),

View File

@ -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),

View File

@ -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",

View File

@ -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

1 asm/non_matchings/code/z_en_a_keep/EnAObj_Init.s EnAObj_Init 0x800A5AC0 0x2B
2678 asm/non_matchings/code/listalloc/func_80174B20.s func_80174B20 0x80174B20 0x20
2679 asm/non_matchings/code/listalloc/func_80174BA0.s func_80174BA0 0x80174BA0 0x14
2680 asm/non_matchings/code/main/main.s main 0x80174BF0 0xC8
2681 asm/non_matchings/code/padmgr/Padmgr_GetControllerBitmask.s asm/non_matchings/code/padmgr/PadMgr_GetValidControllersMask.s Padmgr_GetControllerBitmask PadMgr_GetValidControllersMask 0x80174F10 0x5
2682 asm/non_matchings/code/padmgr/func_80174F24.s asm/non_matchings/code/padmgr/PadMgr_SetRumbleRetraceCallback.s func_80174F24 PadMgr_SetRumbleRetraceCallback 0x80174F24 0x8
2683 asm/non_matchings/code/padmgr/func_80174F44.s asm/non_matchings/code/padmgr/PadMgr_UnsetRumbleRetraceCallback.s func_80174F44 PadMgr_UnsetRumbleRetraceCallback 0x80174F44 0xE
2684 asm/non_matchings/code/padmgr/func_80174F7C.s asm/non_matchings/code/padmgr/PadMgr_SetInputRetraceCallback.s func_80174F7C PadMgr_SetInputRetraceCallback 0x80174F7C 0x8
2685 asm/non_matchings/code/padmgr/func_80174F9C.s asm/non_matchings/code/padmgr/PadMgr_UnsetInputRetraceCallback.s func_80174F9C PadMgr_UnsetInputRetraceCallback 0x80174F9C 0xE
2686 asm/non_matchings/code/padmgr/Padmgr_GetEventCallback.s asm/non_matchings/code/padmgr/PadMgr_AcquireSerialEventQueue.s Padmgr_GetEventCallback PadMgr_AcquireSerialEventQueue 0x80174FD4 0xD
2687 asm/non_matchings/code/padmgr/func_80175008.s asm/non_matchings/code/padmgr/PadMgr_VoiceAcquireSerialEventQueue.s func_80175008 PadMgr_VoiceAcquireSerialEventQueue 0x80175008 0xD
2688 asm/non_matchings/code/padmgr/Padmgr_SetEventCallback.s asm/non_matchings/code/padmgr/PadMgr_ReleaseSerialEventQueue.s Padmgr_SetEventCallback PadMgr_ReleaseSerialEventQueue 0x8017503C 0xC
2689 asm/non_matchings/code/padmgr/func_8017506C.s asm/non_matchings/code/padmgr/PadMgr_VoiceReleaseSerialEventQueue.s func_8017506C PadMgr_VoiceReleaseSerialEventQueue 0x8017506C 0xC
2690 asm/non_matchings/code/padmgr/Padmgr_Lock.s asm/non_matchings/code/padmgr/PadMgr_LockPadData.s Padmgr_Lock PadMgr_LockPadData 0x8017509C 0xC
2691 asm/non_matchings/code/padmgr/Padmgr_Unlock.s asm/non_matchings/code/padmgr/PadMgr_UnlockPadData.s Padmgr_Unlock PadMgr_UnlockPadData 0x801750CC 0xC
2692 asm/non_matchings/code/padmgr/func_801750FC.s asm/non_matchings/code/padmgr/PadMgr_UpdateRumble.s func_801750FC PadMgr_UpdateRumble 0x801750FC 0x9A
2693 asm/non_matchings/code/padmgr/func_80175364.s asm/non_matchings/code/padmgr/PadMgr_RumbleStop.s func_80175364 PadMgr_RumbleStop 0x80175364 0x34
2694 asm/non_matchings/code/padmgr/func_80175434.s asm/non_matchings/code/padmgr/PadMgr_RumblePause.s func_80175434 PadMgr_RumblePause 0x80175434 0x6
2695 asm/non_matchings/code/padmgr/func_8017544C.s asm/non_matchings/code/padmgr/PadMgr_RumbleSetSingle.s func_8017544C PadMgr_RumbleSetSingle 0x8017544C 0xA
2696 asm/non_matchings/code/padmgr/PadMgr_RumbleSet.s PadMgr_RumbleSet 0x80175474 0x13
2697 asm/non_matchings/code/padmgr/PadMgr_ControllerHasRumblePak.s PadMgr_ControllerHasRumblePak 0x801754C0 0x8
2698 asm/non_matchings/code/padmgr/Padmgr_CalcStickEdges.s asm/non_matchings/code/padmgr/PadMgr_AdjustInput.s Padmgr_CalcStickEdges PadMgr_AdjustInput 0x801754E0 0xB1
2699 asm/non_matchings/code/padmgr/Padmgr_ParseState.s asm/non_matchings/code/padmgr/PadMgr_UpdateInputs.s Padmgr_ParseState PadMgr_UpdateInputs 0x801757A4 0x86
2700 asm/non_matchings/code/padmgr/func_801759BC.s asm/non_matchings/code/padmgr/PadMgr_InitVoice.s func_801759BC PadMgr_InitVoice 0x801759BC 0x49
2701 asm/non_matchings/code/padmgr/func_80175AE0.s asm/non_matchings/code/padmgr/PadMgr_UpdateConnections.s func_80175AE0 PadMgr_UpdateConnections 0x80175AE0 0x68
2702 asm/non_matchings/code/padmgr/Padmgr_Update.s asm/non_matchings/code/padmgr/PadMgr_HandleRetrace.s Padmgr_Update PadMgr_HandleRetrace 0x80175C80 0x6F
2703 asm/non_matchings/code/padmgr/Padmgr_Stop.s asm/non_matchings/code/padmgr/PadMgr_HandlePreNMI.s Padmgr_Stop PadMgr_HandlePreNMI 0x80175E3C 0xB
2704 asm/non_matchings/code/padmgr/func_80175E68.s asm/non_matchings/code/padmgr/PadMgr_GetInputNoLock.s func_80175E68 PadMgr_GetInputNoLock 0x80175E68 0x4C
2705 asm/non_matchings/code/padmgr/Padmgr_GetInput.s asm/non_matchings/code/padmgr/PadMgr_GetInput.s Padmgr_GetInput PadMgr_GetInput 0x80175F98 0xF
2706 asm/non_matchings/code/padmgr/Padmgr_GetInput2.s asm/non_matchings/code/padmgr/PadMgr_GetInput2.s Padmgr_GetInput2 PadMgr_GetInput2 0x80175FD4 0xF
2707 asm/non_matchings/code/padmgr/Padmgr_ThreadEntry.s asm/non_matchings/code/padmgr/PadMgr_ThreadEntry.s Padmgr_ThreadEntry PadMgr_ThreadEntry 0x80176010 0x61
2708 asm/non_matchings/code/padmgr/PadMgr_Init.s PadMgr_Init 0x80176194 0x3B
2709 asm/non_matchings/code/sched/Sched_SwapFramebuffer.s Sched_SwapFramebuffer 0x80176280 0x25
2710 asm/non_matchings/code/sched/Sched_RetraceUpdateFramebuffer.s Sched_RetraceUpdateFramebuffer 0x80176314 0x14