Merge pull request #37 from ProjectRevoTPP/decompile_controller

decompile controller.c
This commit is contained in:
Revo
2022-10-23 01:18:05 -04:00
committed by GitHub
8 changed files with 308 additions and 5 deletions

43
include/controller.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef _CONTROLLER_H_
#define _CONTROLLER_H_
struct Controller {
/* 0x00 */ s16 contId;
/* 0x02 */ s16 rawStickX;
/* 0x04 */ s16 rawStickY;
/* 0x06 */ u16 buttonDown;
/* 0x08 */ u16 buttonPressed;
/* 0x0A */ u16 unkA;
char fillerC[2];
/* 0x0E */ u16 unkE;
/* 0x10 */ float stickMag;
/* 0x14 */ float stickX;
/* 0x18 */ float stickY;
/* 0x1C */ OSContStatus *statusData;
/* 0x20 */ OSContPad *controllerData;
};
extern struct Controller gControllers[4];
extern OSMesgQueue gSIEventMesgQueue;
extern u8 gControllerBits;
extern u8 gEepromProbe;
extern OSContStatus gControllerStatuses[4];
extern OSContPad gControllerPads[4];
extern OSMesg gSIEventMesgBuf[1];
extern OSMesg gEepromMesgBuf[1];
extern OSMesgQueue gEepromMesgQueue;
void Cont_InitControllers(void);
void Cont_AdjustAnalogStick(struct Controller *controller);
void Cont_StartReadInputs(void);
void Cont_ReadInputs(void);
u8 Cont_GetControllerBits(void);
s32 Cont_IsEepromPresent(void);
s32 Cont_AttemptReadEeprom(u8* buffer, u32 size, s32 inaddr);
s32 Cont_AttemptWriteEeprom(u8* buffer, u32 size, s32 inaddr);
void Cont_BlockEepromQueue(void);
void Cont_NoBlockEepromQueue(void);
void Cont_InitEepromQueue(void);
u8 Cont_SetupControllers(void);
#endif // _CONTROLLER_H_

View File

@@ -25,4 +25,8 @@ typedef unsigned long uintptr_t;
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define ALIGN4(val) (((val) + 0x3) & ~0x3)
#define ALIGN8(val) (((val) + 0x7) & ~0x7)
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
#endif

View File

@@ -41,7 +41,7 @@ segments:
- [0x3A80, asm] # transition loader
- [0x3FB0, asm] # PRES-JPEG decoder
- [0x60A0, asm] #
- [0x6430, asm] # controller code
- [0x6430, c, controller] # controller code
- [0x6A40, asm] #
- [0x6BC0, asm] #
- [0x75F0, asm] # stage loader
@@ -366,6 +366,8 @@ segments:
- {vram: 0x8007F190, type: .bss, name: main}
- {vram: 0x80081900, type: .bss, name: rsp}
- {vram: 0x80083CA0, type: .bss, name: unk_bss}
- {vram: 0x800A7320, type: .bss, name: controller}
- {vram: 0x800A7420, type: .bss, name: unk_bss_3}
- {vram: 0x800A74C0, type: .bss, name: crash_screen}
- {vram: 0x800A7EA0, type: .bss, name: unk_bss_2}
- {vram: 0x80103880, type: .bss, name: libultra/gu/rotate}

230
src/controller.c Normal file
View File

@@ -0,0 +1,230 @@
#include <ultra64.h>
#include "controller.h"
// TODO: Identify/move to header
extern s16 func_8000A360(float, float);
struct Controller gControllers[4];
OSMesgQueue gSIEventMesgQueue;
u8 gControllerBits;
u8 gEepromProbe;
OSContStatus gControllerStatuses[4];
OSContPad gControllerPads[4];
OSMesg gSIEventMesgBuf[1];
OSMesg gEepromMesgBuf[1];
OSMesgQueue gEepromMesgQueue;
/*
* Initialize the gControllers structs. Clear each member, then set their cont
* id and set the status and pads pointers.
*/
void Cont_InitControllers(void) {
int i;
// clear each gControllers member.
for(i = 0; i < MAXCONTROLLERS; i++) {
bzero((void*)&gControllers[i], sizeof(struct Controller));
}
// Initialize each connected controller.
for(i = 0; i < MAXCONTROLLERS; i++) {
// If the bit is set in this bitfield for each iteration, it means
// the controller is connected. Set the ID and pointers respectively.
if(gControllerBits & (1 << i)) {
gControllers[i].contId = (i+1); // indexed by 1. (cont 1, cont 2, etc)
gControllers[i].statusData = &gControllerStatuses[i];
gControllers[i].controllerData = &gControllerPads[i];
}
}
}
/*
* Take the updated controller struct and calculate
* the new x, y, and distance floats.
*/
void Cont_AdjustAnalogStick(struct Controller *controller) {
// reset the controller's x and y floats.
controller->stickX = 0.0f;
controller->stickY = 0.0f;
// modulate the rawStickX and rawStickY to be the new f32 values by adding/subtracting 6.
if (controller->rawStickX <= -8) {
controller->stickX = controller->rawStickX + 6;
}
if (controller->rawStickX >= 8) {
controller->stickX = controller->rawStickX - 6;
}
if (controller->rawStickY <= -8) {
controller->stickY = controller->rawStickY + 6;
}
if (controller->rawStickY >= 8) {
controller->stickY = controller->rawStickY - 6;
}
// calculate f32 magnitude from the center by vector length.
controller->stickMag =
sqrtf(controller->stickX * controller->stickX + controller->stickY * controller->stickY);
// magnitude cannot exceed 64.0f: if it does, modify the values appropriately to
// flatten the values down to the allowed maximum value.
if (controller->stickMag > 64) {
controller->stickX *= 64 / controller->stickMag;
controller->stickY *= 64 / controller->stickMag;
controller->stickMag = 64;
}
if (controller->stickMag > 0.0f) {
controller->unkE = func_8000A360(-controller->stickY, controller->stickX);
}
}
/*
* Start the reading of the controller inputs into the current structs.
*/
void Cont_StartReadInputs(void) {
Cont_BlockEepromQueue();
osContStartReadData(&gSIEventMesgQueue);
}
/*
* Read in the inputs into the pads and then update the controller structs accordingly based on
* new button masks and held button masks.
*/
void Cont_ReadInputs(void) {
s32 i;
struct Controller *controller = &gControllers[0];
osRecvMesg(&gSIEventMesgQueue, NULL, OS_MESG_BLOCK);
osContGetReadData(&gControllerPads[0]);
Cont_NoBlockEepromQueue();
for(i = 0; i < 4; i++, controller++) {
// if the contId is not 0, it means the controller is initialized.
if(controller->contId != 0) {
controller->rawStickX = controller->controllerData->stick_x;
controller->rawStickY = controller->controllerData->stick_y;
controller->buttonPressed = controller->controllerData->button
& (controller->controllerData->button ^ controller->buttonDown);
controller->unkA = controller->buttonDown
& (controller->controllerData->button ^ controller->buttonDown);
controller->buttonDown = controller->controllerData->button;
Cont_AdjustAnalogStick(controller);
} else {
controller->buttonPressed = 0;
controller->unkA = 0;
controller->buttonDown = 0;
}
}
func_8000B330();
}
/*
* Retrieve the current controller bits.
*/
u8 Cont_GetControllerBits(void) {
return gControllerBits;
}
/*
* Check if an EEPROM is connected. Since probe 0x00 is not connected and
* 0x01 and 0x02 are otherwise, a non-0 probe means it is connected.
*/
s32 Cont_IsEepromPresent(void) {
return gEepromProbe != 0;
}
/*
* Attempt to read from EEPROM up to 4 times given a buffer and size and inaddr.
* A return of 0 indicates success while -1 is an EEPROM error.
*/
s32 Cont_AttemptReadEeprom(u8* buffer, u32 size, s32 inaddr) {
s32 result = 1;
if (gEepromProbe) {
s32 i = 4;
Cont_BlockEepromQueue();
do {
// Get the number of 8-byte buffers to send, since we are sending in 8
// byte chunks.
s32 count = size / 8;
// this value must be a multiple of 8 due to hardware restrictions as
// specified by http://n64devkit.square7.ch/n64man/os/osEepromLongRead.htm.
// Force the value to be a multiple of 8 to adhere to the restrictions.
s32 address = ALIGN8(inaddr);
i --;
// once the result is 0 (success), exit from the loop since the write was successful.
result = osEepromLongRead(&gSIEventMesgQueue, count, buffer, address);
} while (i > 0 && result);
Cont_NoBlockEepromQueue();
}
return result;
}
/*
* Attempt to write to EEPROM up to 4 times given a buffer and size and inaddr.
* A return of 0 indicates success while -1 is an EEPROM error.
*/
s32 Cont_AttemptWriteEeprom(u8* buffer, u32 size, s32 inaddr) {
s32 result = 1;
if (gEepromProbe) {
s32 i = 4;
Cont_BlockEepromQueue();
do {
// Get the number of 8-byte buffers to send, since we are sending in 8
// byte chunks.
s32 count = size / 8;
// this value must be a multiple of 8 due to hardware restrictions as
// specified by http://n64devkit.square7.ch/n64man/os/osEepromLongRead.htm.
// Force the value to be a multiple of 8 to adhere to the restrictions.
s32 address = ALIGN8(inaddr);
i --;
// once the result is 0 (success), exit from the loop since the write was successful.
result = osEepromLongWrite(&gSIEventMesgQueue, count, buffer, address);
} while (i > 0 && result);
Cont_NoBlockEepromQueue();
}
return result;
}
/*
* Run a Block Mesg against the Eeprom queue.
*/
void Cont_BlockEepromQueue(void) {
osRecvMesg(&gEepromMesgQueue, NULL, OS_MESG_BLOCK);
}
/*
* Run a No Block Mesg against the Eeprom queue.
*/
void Cont_NoBlockEepromQueue(void) {
osSendMesg(&gEepromMesgQueue, NULL, OS_MESG_NOBLOCK);
}
/*
* Initialize the Eeprom Mesg queue.
*/
void Cont_InitEepromQueue(void) {
osCreateMesgQueue(&gEepromMesgQueue, gEepromMesgBuf, 1);
osSendMesg(&gEepromMesgQueue, NULL, OS_MESG_NOBLOCK);
}
/*
* Setup the controllers for initial use by initializing the EEPROM queue
* and SI Event queues. EEPROM probing was handled by game_init.c in Super
* Mario 64 which also handled the controllers in the same file. Since
* Nintendo EAD is also credited with co-developing Pokemon Stadium, this
* organization may be a holdover from that era.
*/
u8 Cont_SetupControllers(void) {
Cont_InitEepromQueue();
osCreateMesgQueue(&gSIEventMesgQueue, gSIEventMesgBuf, 1);
osSetEventMesg(OS_EVENT_SI, &gSIEventMesgQueue, NULL);
osContInit(&gSIEventMesgQueue, &gControllerBits, &gControllerStatuses[0]);
gEepromProbe = osEepromProbe(&gSIEventMesgQueue);
Cont_InitControllers();
return gControllerBits;
}

View File

@@ -86,8 +86,8 @@ void crash_screen_wait_for_button_combo(void) {
s32 i = 0;
do {
func_80005A84();
func_80005AB0();
Cont_StartReadInputs();
Cont_ReadInputs();
if (((u16*)D_80068BA0[0])[4] != 0) {
if (((u16*)D_80068BA0[0])[4] == gCrashScreenUnlockInputs[i++]) {
// have we reached the end of the array? exit the sleep loop.

View File

@@ -1,4 +1,4 @@
#include <ultra64.h>
// used for padding. Splat cant auto gen these I guess
static u8 unk_bss[0x800A74C0-0x80083CA0];
static u8 unk_bss[0x800A7320-0x80083CA0];

4
src/unk_bss_3.c Normal file
View File

@@ -0,0 +1,4 @@
#include <ultra64.h>
// used for padding. Splat cant auto gen these I guess
static u8 unk_bss[0x800A74C0-0x800A7420];

View File

@@ -422,4 +422,24 @@ Memmap_GetFragmentBaseVaddr = 0x800020CC;
Memmap_GetFragmentVaddr = 0x800020E0;
Memmap_GetFragmentVaddrMask = 0x80002144;
Memmap_ClearFragmentMemmap = 0x8000218C;
Memmap_GetLoadedFragmentVaddr = 0x800021A8;
Memmap_GetLoadedFragmentVaddr = 0x800021A8;
gControllerStatuses = 0x800A73D0;
gControllerPads = 0x800A73E0;
gSIEventMesgQueue = 0x800A73B0;
gControllerBits = 0x800A73C8;
gEepromProbe = 0x800A73C9;
gSIEventMesgBuf = 0x800A73F8;
gEepromMesgQueue = 0x800A7400;
gEepromMesgBuf = 0x800A73FC;
Cont_InitControllers = 0x80005830;
Cont_AdjustAnalogStick = 0x80005950;
Cont_StartReadInputs = 0x80005A84;
Cont_ReadInputs = 0x80005AB0;
Cont_GetControllerBits = 0x80005B90;
Cont_IsEepromPresent = 0x80005B9C;
Cont_AttemptReadEeprom = 0x80005BAC;
Cont_AttemptWriteEeprom = 0x80005C64;
Cont_BlockEepromQueue = 0x80005D1C;
Cont_NoBlockEepromQueue = 0x80005D48;
Cont_InitEepromQueue = 0x80005D74;
Cont_SetupControllers = 0x80005DB8;