mirror of
https://github.com/pret/pokestadium.git
synced 2026-03-22 01:34:25 -05:00
227 lines
7.6 KiB
C
227 lines
7.6 KiB
C
#include <ultra64.h>
|
|
#include "controller.h"
|
|
#include "gb_tower.h"
|
|
#include "math_util.h"
|
|
|
|
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 = MathUtil_Atan2s(-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;
|
|
}
|