mirror of
https://github.com/pret/pokestadium.git
synced 2026-10-01 22:37:28 -05:00
Merge pull request #37 from ProjectRevoTPP/decompile_controller
decompile controller.c
This commit is contained in:
43
include/controller.h
Normal file
43
include/controller.h
Normal 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_
|
||||
@@ -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
|
||||
|
||||
@@ -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
230
src/controller.c
Normal 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;
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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
4
src/unk_bss_3.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <ultra64.h>
|
||||
|
||||
// used for padding. Splat cant auto gen these I guess
|
||||
static u8 unk_bss[0x800A74C0-0x800A7420];
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user