You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
Merge pull request #595 from Arceveti/develop/2.1.0-four-controllers-base
4 controllers support + osContCh optimization
This commit is contained in:
@@ -21,7 +21,7 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin
|
||||
- **Fazana**: PuppyLib, ucode swapping, audio load time optimisations (with Arctic), general hacker qol improvements, visual debug
|
||||
- **Reonu**: Starting the project/repo, widescreen, reonucam, various defines for hacker QoL
|
||||
- **JoshDuMan**: Decomp guy, general assistance
|
||||
- **Arceveti**: Silhouette, shadow optimisation, better hanging, breath meter
|
||||
- **Arceveti**: Silhouette, shadow optimisation, better hanging, breath meter, 4 controller support
|
||||
- **axollyon**: Console testing, bugfixes, idea-guying, and had a hand in silhouettes
|
||||
- **Wiseguy**: World scale reimplementation, silhouette, graph node optimisations, instant input patch, cake screen fix, segmented code support, and various optimizations/fixes
|
||||
- **Kaze**: Graph node optimisations, automatic optimal collision distance
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
.word 0x00000000 /* Unknown */
|
||||
.word 0x00000000 /* Unknown */
|
||||
.ascii INTERNAL_ROM_NAME /* Internal ROM name */
|
||||
#if defined(USE_GAMECUBE_CONTROLLER)
|
||||
#if defined(EMU_DEFAULT_TO_GCN)
|
||||
/* Advanced homebrew ROM header bytes: https://n64brew.dev/wiki/ROM_Header#Advanced_Homebrew_ROM_Header */
|
||||
.word 0x82000000
|
||||
#else
|
||||
.word 0x00000000 /* Unknown */
|
||||
#endif
|
||||
.word 0x0000004E /* Cartridge */
|
||||
#if defined(EEP4K) && !defined(USE_GAMECUBE_CONTROLLER)
|
||||
#if defined(EEP4K) && !defined(EMU_DEFAULT_TO_GCN)
|
||||
.ascii "SM" /* Cartridge ID */
|
||||
#else
|
||||
.ascii "ED" /* Cartridge ID */
|
||||
|
||||
@@ -10,12 +10,32 @@
|
||||
*/
|
||||
#define INTERNAL_ROM_NAME "HackerSM64 "
|
||||
|
||||
/**
|
||||
* Force the game to delete any existing save data originating from a different hack. This requires INTERNAL_ROM_NAME to be unique to work properly.
|
||||
* It is recommended to enable this if any significant changes to the save file are made that could cause issues with this or other hacks.
|
||||
* NOTE: Using save editors with this define will likely just end up wiping your save, since SM64 specific save editors most likely use hardcoded save magic.
|
||||
*/
|
||||
// #define UNIQUE_SAVE_DATA
|
||||
|
||||
/**
|
||||
* Enables Rumble Pak Support.
|
||||
* Currently not recommended, as it may cause random crashes.
|
||||
*/
|
||||
// #define ENABLE_RUMBLE (1 || VERSION_SH)
|
||||
|
||||
/**
|
||||
* The maximum number of supported players/controllers. 1-4.
|
||||
* This will save performance if the player has extra unused controllers plugged in.
|
||||
* NOTE: Default is 2, maximum is 4.
|
||||
* NOTE: This needs to be at least 2 for now for gamecube controller swap to work.
|
||||
*/
|
||||
#define MAX_NUM_PLAYERS 2
|
||||
|
||||
/**
|
||||
* Informs supported emulators to default to GameCube controller inputs.
|
||||
*/
|
||||
// #define EMU_DEFAULT_TO_GCN
|
||||
|
||||
/**
|
||||
* Screen Size Defines.
|
||||
*/
|
||||
@@ -29,18 +49,6 @@
|
||||
#define BORDER_HEIGHT_CONSOLE 0
|
||||
#define BORDER_HEIGHT_EMULATOR 0
|
||||
|
||||
/**
|
||||
* Force the game to delete any existing save data originating from a different hack. This requires INTERNAL_ROM_NAME to be unique to work properly.
|
||||
* It is recommended to enable this if any significant changes to the save file are made that could cause issues with this or other hacks.
|
||||
* NOTE: Using save editors with this define will likely just end up wiping your save, since SM64 specific save editors most likely use hardcoded save magic.
|
||||
*/
|
||||
// #define UNIQUE_SAVE_DATA
|
||||
|
||||
/**
|
||||
* Informs supported emulators to default to gamecube controller inputs.
|
||||
*/
|
||||
// #define USE_GAMECUBE_CONTROLLER
|
||||
|
||||
/**
|
||||
* RCVI hack. Increases performance on emulator, and does nothing on console.
|
||||
* Might break on some emulators. Use at your own risk, and don't use it unless you actually need the extra performance.
|
||||
|
||||
@@ -112,6 +112,11 @@ typedef struct {
|
||||
|
||||
/* Controller type */
|
||||
|
||||
// Console ID:
|
||||
#define CONT_CONSOLE_MASK (0x3 << 3) // 0x0018 | 0: N64, 1: Dolphin
|
||||
#define CONT_CONSOLE_N64 ( 0 << 3) // 0x0000
|
||||
#define CONT_CONSOLE_GCN ( 1 << 3) // 0x0008
|
||||
|
||||
#define CONT_ABSOLUTE 0x0001
|
||||
#define CONT_RELATIVE 0x0002
|
||||
#define CONT_JOYPORT 0x0004
|
||||
@@ -194,9 +199,6 @@ typedef struct {
|
||||
#define CONT_ERR_VOICE_WORD 14
|
||||
#define CONT_ERR_VOICE_NO_RESPONSE 15
|
||||
|
||||
#define CONT_TYPE_N64 0
|
||||
#define CONT_TYPE_GCN 1
|
||||
|
||||
|
||||
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
|
||||
|
||||
@@ -213,7 +215,6 @@ typedef struct {
|
||||
*
|
||||
*/
|
||||
|
||||
extern u8 __osControllerTypes[MAXCONTROLLERS];
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
|
||||
@@ -32,21 +32,19 @@ struct Config {
|
||||
u8 tvType;
|
||||
};
|
||||
|
||||
struct Controller {
|
||||
/*0x00*/ s16 rawStickX; //
|
||||
/*0x02*/ s16 rawStickY; //
|
||||
/*0x04*/ f32 stickX; // [-64, 64] positive is right
|
||||
/*0x08*/ f32 stickY; // [-64, 64] positive is up
|
||||
/*0x0C*/ f32 stickMag; // distance from center [0, 64]
|
||||
/*0x10*/ u16 buttonDown;
|
||||
/*0x12*/ u16 buttonPressed;
|
||||
/*0x14*/ u16 buttonReleased;
|
||||
/*0x18*/ OSContStatus *statusData;
|
||||
/*0x1C*/ OSContPadEx *controllerData;
|
||||
#if ENABLE_RUMBLE
|
||||
/*0x20*/ s32 port;
|
||||
#endif
|
||||
};
|
||||
typedef struct Controller {
|
||||
/*0x00*/ s16 rawStickX; // Analog stick [-128, 128] positive is right. Used for menus.
|
||||
/*0x02*/ s16 rawStickY; // Analog stick [-128, 128] positive is up. Used for menus.
|
||||
/*0x04*/ f32 stickX; // Analog stick [-64, 64] positive is right. Used for gameplay.
|
||||
/*0x08*/ f32 stickY; // Analog stick [-64, 64] positive is up. Used for gameplay.
|
||||
/*0x0C*/ f32 stickMag; // Analog stick distance from center [0, 64]. Used for gameplay.
|
||||
/*0x10*/ u16 buttonDown; // Buttons held down on the current frame.
|
||||
/*0x12*/ u16 buttonPressed; // Buttons pressed on the current frame but not held on the previous frame.
|
||||
/*0x14*/ u16 buttonReleased; // Burrons released on the current frame and held on the previous frame.
|
||||
/*0x18*/ OSContStatus* statusData; // Pointer to the controller status data in gControllerStatuses.
|
||||
/*0x1C*/ OSContPadEx* controllerData; // Pointer to the raw input data in gControllerPads.
|
||||
/*0x20*/ s32 port; // The port index this controller is plugged into [0, 3].
|
||||
} Controller; /*0x24*/
|
||||
|
||||
// -- Booleans --
|
||||
|
||||
|
||||
2
sm64.ld
2
sm64.ld
@@ -184,8 +184,6 @@ SECTIONS
|
||||
lib/PR/audio/n_aspMain.o(.text*);
|
||||
lib/PR/hvqm/hvqm2sp1.o(.text*);
|
||||
_mainSegmentTextEnd = .;
|
||||
/* Overwrite a libultra function with its modified counterpart for GCN controller support */
|
||||
__osContGetInitData = __osContGetInitDataEx;
|
||||
|
||||
/* data */
|
||||
BUILD_DIR/asm/n64_assert.o(.*data*);
|
||||
|
||||
@@ -82,8 +82,8 @@ UNUSED static u16 sDebugTextKeySequence[] = {
|
||||
};
|
||||
static s16 sDebugTextKey = 0;
|
||||
UNUSED void handle_debug_key_sequences(void) {
|
||||
if (gPlayer3Controller->buttonPressed != 0) {
|
||||
if (sDebugTextKeySequence[sDebugTextKey++] == gPlayer3Controller->buttonPressed) {
|
||||
if (gPlayer1Controller->buttonPressed != 0) {
|
||||
if (sDebugTextKeySequence[sDebugTextKey++] == gPlayer1Controller->buttonPressed) {
|
||||
if (sDebugTextKey == ARRAY_COUNT(sDebugTextKeySequence)) {
|
||||
sDebugTextKey = 0;
|
||||
gShowDebugText ^= 1;
|
||||
|
||||
@@ -71,8 +71,8 @@ void hoot_player_set_yaw(void) {
|
||||
s16 turnSpeed = gMarioState->intendedMag * 0x20;
|
||||
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, gMarioState->intendedYaw, turnSpeed);
|
||||
#else
|
||||
s16 stickX = gPlayer3Controller->rawStickX;
|
||||
s16 stickY = gPlayer3Controller->rawStickY;
|
||||
s16 stickX = gPlayer1Controller->rawStickX;
|
||||
s16 stickY = gPlayer1Controller->rawStickY;
|
||||
if (stickX < 10 && stickX > -10) stickX = 0;
|
||||
if (stickY < 10 && stickY > -10) stickY = 0;
|
||||
o->oMoveAngleYaw -= 5 * stickX;
|
||||
|
||||
@@ -35,9 +35,6 @@
|
||||
// Emulators that the Instant Input patch should not be applied to
|
||||
#define INSTANT_INPUT_BLACKLIST (EMU_CONSOLE | EMU_WIIVC | EMU_ARES | EMU_SIMPLE64 | EMU_CEN64)
|
||||
|
||||
// First 3 controller slots
|
||||
struct Controller gControllers[3];
|
||||
|
||||
// Gfx handlers
|
||||
struct SPTask *gGfxSPTask;
|
||||
Gfx *gDisplayListHead;
|
||||
@@ -45,10 +42,10 @@ u8 *gGfxPoolEnd;
|
||||
struct GfxPool *gGfxPool;
|
||||
|
||||
// OS Controllers
|
||||
OSContStatus gControllerStatuses[4];
|
||||
OSContPadEx gControllerPads[4];
|
||||
u8 gControllerBits;
|
||||
s8 gGamecubeControllerPort = -1; // HackerSM64: This is set to -1 if there's no GC controller, 0 if there's one in the first port and 1 if there's one in the second port.
|
||||
struct Controller gControllers[MAXCONTROLLERS];
|
||||
OSContStatus gControllerStatuses[MAXCONTROLLERS];
|
||||
OSContPadEx gControllerPads[MAXCONTROLLERS];
|
||||
u8 gControllerBits = 0b0000;
|
||||
u8 gBorderHeight;
|
||||
#ifdef VANILLA_STYLE_CUSTOM_DEBUG
|
||||
u8 gCustomDebugMode;
|
||||
@@ -89,10 +86,11 @@ u16 sRenderingFramebuffer = 0;
|
||||
// Goddard Vblank Function Caller
|
||||
void (*gGoddardVblankCallback)(void) = NULL;
|
||||
|
||||
// Defined controller slots
|
||||
struct Controller *gPlayer1Controller = &gControllers[0];
|
||||
struct Controller *gPlayer2Controller = &gControllers[1];
|
||||
struct Controller *gPlayer3Controller = &gControllers[2]; // Probably debug only, see note below
|
||||
// Defined player slots. Anything above MAX_NUM_PLAYERS should not be used.
|
||||
struct Controller* const gPlayer1Controller = &gControllers[0];
|
||||
struct Controller* const gPlayer2Controller = &gControllers[1];
|
||||
struct Controller* const gPlayer3Controller = &gControllers[2];
|
||||
struct Controller* const gPlayer4Controller = &gControllers[3];
|
||||
|
||||
// Title Screen Demo Handler
|
||||
struct DemoInput *gCurrDemoInput = NULL;
|
||||
@@ -498,36 +496,25 @@ UNUSED static void record_demo(void) {
|
||||
*/
|
||||
void run_demo_inputs(void) {
|
||||
// Eliminate the unused bits.
|
||||
gControllers[0].controllerData->button &= VALID_BUTTONS;
|
||||
gPlayer1Controller->controllerData->button &= VALID_BUTTONS;
|
||||
|
||||
// Check if a demo inputs list exists and if so,
|
||||
// run the active demo input list.
|
||||
if (gCurrDemoInput != NULL) {
|
||||
// Clear player 2's inputs if they exist. Player 2's controller
|
||||
// cannot be used to influence a demo. At some point, Nintendo
|
||||
// may have planned for there to be a demo where 2 players moved
|
||||
// around instead of just one, so clearing player 2's influence from
|
||||
// the demo had to have been necessary to perform this. Co-op mode, perhaps?
|
||||
if (gControllers[1].controllerData != NULL) {
|
||||
gControllers[1].controllerData->stick_x = 0;
|
||||
gControllers[1].controllerData->stick_y = 0;
|
||||
gControllers[1].controllerData->button = 0;
|
||||
}
|
||||
|
||||
// The timer variable being 0 at the current input means the demo is over.
|
||||
// Set the button to the END_DEMO mask to end the demo.
|
||||
if (gCurrDemoInput->timer == 0) {
|
||||
gControllers[0].controllerData->stick_x = 0;
|
||||
gControllers[0].controllerData->stick_y = 0;
|
||||
gControllers[0].controllerData->button = END_DEMO;
|
||||
gPlayer1Controller->controllerData->stick_x = 0;
|
||||
gPlayer1Controller->controllerData->stick_y = 0;
|
||||
gPlayer1Controller->controllerData->button = END_DEMO;
|
||||
} else {
|
||||
// Backup the start button if it is pressed, since we don't want the
|
||||
// demo input to override the mask where start may have been pressed.
|
||||
u16 startPushed = gControllers[0].controllerData->button & START_BUTTON;
|
||||
u16 startPushed = (gPlayer1Controller->controllerData->button & START_BUTTON);
|
||||
|
||||
// Perform the demo inputs by assigning the current button mask and the stick inputs.
|
||||
gControllers[0].controllerData->stick_x = gCurrDemoInput->rawStickX;
|
||||
gControllers[0].controllerData->stick_y = gCurrDemoInput->rawStickY;
|
||||
gPlayer1Controller->controllerData->stick_x = gCurrDemoInput->rawStickX;
|
||||
gPlayer1Controller->controllerData->stick_y = gCurrDemoInput->rawStickY;
|
||||
|
||||
// To assign the demo input, the button information is stored in
|
||||
// an 8-bit mask rather than a 16-bit mask. this is because only
|
||||
@@ -536,11 +523,11 @@ void run_demo_inputs(void) {
|
||||
// upper 4 bits (A, B, Z, and Start) and shift then left by 8 to
|
||||
// match the correct input mask. We then add this to the masked
|
||||
// lower 4 bits to get the correct button mask.
|
||||
gControllers[0].controllerData->button =
|
||||
gPlayer1Controller->controllerData->button =
|
||||
((gCurrDemoInput->buttonMask & 0xF0) << 8) + ((gCurrDemoInput->buttonMask & 0xF));
|
||||
|
||||
// If start was pushed, put it into the demo sequence being input to end the demo.
|
||||
gControllers[0].controllerData->button |= startPushed;
|
||||
gPlayer1Controller->controllerData->button |= startPushed;
|
||||
|
||||
// Run the current demo input's timer down. if it hits 0, advance the demo input list.
|
||||
if (--gCurrDemoInput->timer == 0) {
|
||||
@@ -594,14 +581,12 @@ void adjust_analog_stick(struct Controller *controller) {
|
||||
* Update the controller struct with available inputs if present.
|
||||
*/
|
||||
void read_controller_inputs(s32 threadID) {
|
||||
s32 i;
|
||||
|
||||
// If any controllers are plugged in, update the controller information.
|
||||
if (gControllerBits) {
|
||||
if (threadID == THREAD_5_GAME_LOOP) {
|
||||
osRecvMesg(&gSIEventMesgQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
|
||||
}
|
||||
osContGetReadDataEx(&gControllerPads[0]);
|
||||
osContGetReadDataEx(gControllerPads);
|
||||
#if ENABLE_RUMBLE
|
||||
release_rumble_pak_control();
|
||||
#endif
|
||||
@@ -610,65 +595,67 @@ void read_controller_inputs(s32 threadID) {
|
||||
run_demo_inputs();
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct Controller *controller = &gControllers[i];
|
||||
for (s32 cont = 0; cont < MAX_NUM_PLAYERS; cont++) {
|
||||
struct Controller* controller = &gControllers[cont];
|
||||
OSContPadEx* controllerData = controller->controllerData;
|
||||
|
||||
// if we're receiving inputs, update the controller struct with the new button info.
|
||||
if (controller->controllerData != NULL) {
|
||||
// HackerSM64: Swaps Z and L, only on console, and only when playing with a GameCube controller.
|
||||
if ((gEmulator & EMU_CONSOLE) && i == gGamecubeControllerPort) {
|
||||
u32 oldButton = controller->controllerData->button;
|
||||
if (controller->statusData->type & CONT_CONSOLE_GCN) {
|
||||
u32 oldButton = controllerData->button;
|
||||
u32 newButton = oldButton & ~(Z_TRIG | L_TRIG);
|
||||
if (oldButton & Z_TRIG) {
|
||||
newButton |= L_TRIG;
|
||||
}
|
||||
if (controller->controllerData->l_trig > 85) { // How far the player has to press the L trigger for it to be considered a Z press. 64 is about 25%. 127 would be about 50%.
|
||||
if (controllerData->l_trig > 85) { // How far the player has to press the L trigger for it to be considered a Z press. 64 is about 25%. 127 would be about 50%.
|
||||
newButton |= Z_TRIG;
|
||||
}
|
||||
controller->controllerData->button = newButton;
|
||||
controllerData->button = newButton;
|
||||
}
|
||||
controller->rawStickX = controller->controllerData->stick_x;
|
||||
controller->rawStickY = controller->controllerData->stick_y;
|
||||
controller->buttonPressed = ~controller->buttonDown & controller->controllerData->button;
|
||||
controller->buttonReleased = ~controller->controllerData->button & controller->buttonDown;
|
||||
controller->rawStickX = controllerData->stick_x;
|
||||
controller->rawStickY = controllerData->stick_y;
|
||||
controller->buttonPressed = (~controller->buttonDown & controllerData->button);
|
||||
controller->buttonReleased = (~controllerData->button & controller->buttonDown);
|
||||
// 0.5x A presses are a good meme
|
||||
controller->buttonDown = controller->controllerData->button;
|
||||
controller->buttonDown = controllerData->button;
|
||||
adjust_analog_stick(controller);
|
||||
} else { // otherwise, if the controllerData is NULL, 0 out all of the inputs.
|
||||
controller->rawStickX = 0;
|
||||
controller->rawStickY = 0;
|
||||
controller->buttonPressed = 0;
|
||||
controller->buttonReleased = 0;
|
||||
controller->buttonDown = 0;
|
||||
controller->stickX = 0;
|
||||
controller->stickY = 0;
|
||||
controller->stickMag = 0;
|
||||
controller->rawStickX = 0;
|
||||
controller->rawStickY = 0;
|
||||
controller->buttonPressed = 0x0000;
|
||||
controller->buttonReleased = 0x0000;
|
||||
controller->buttonDown = 0x0000;
|
||||
controller->stickX = 0.0f;
|
||||
controller->stickY = 0.0f;
|
||||
controller->stickMag = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For some reason, player 1's inputs are copied to player 3's port.
|
||||
// This potentially may have been a way the developers "recorded"
|
||||
// the inputs for demos, despite record_demo existing.
|
||||
gPlayer3Controller->rawStickX = gPlayer1Controller->rawStickX;
|
||||
gPlayer3Controller->rawStickY = gPlayer1Controller->rawStickY;
|
||||
gPlayer3Controller->stickX = gPlayer1Controller->stickX;
|
||||
gPlayer3Controller->stickY = gPlayer1Controller->stickY;
|
||||
gPlayer3Controller->stickMag = gPlayer1Controller->stickMag;
|
||||
gPlayer3Controller->buttonPressed = gPlayer1Controller->buttonPressed;
|
||||
gPlayer3Controller->buttonReleased = gPlayer1Controller->buttonReleased;
|
||||
gPlayer3Controller->buttonDown = gPlayer1Controller->buttonDown;
|
||||
/**
|
||||
* @brief Links a controller struct to the appropriate status and pad.
|
||||
*
|
||||
* @param[out] controller The controller to link.
|
||||
* @param[in ] port The port to get the data from.
|
||||
*/
|
||||
static void assign_controller_data_to_port(struct Controller* controller, int port) {
|
||||
controller->statusData = &gControllerStatuses[port];
|
||||
controller->controllerData = &gControllerPads[port];
|
||||
controller->port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the controller structs to point at the OSCont information.
|
||||
*/
|
||||
void init_controllers(void) {
|
||||
s16 port, cont;
|
||||
int port, cont = 0;
|
||||
int lastUsedPort = -1;
|
||||
|
||||
// Set controller 1 to point to the set of status/pads for input 1 and
|
||||
// init the controllers.
|
||||
gControllers[0].statusData = &gControllerStatuses[0];
|
||||
gControllers[0].controllerData = &gControllerPads[0];
|
||||
osContInit(&gSIEventMesgQueue, &gControllerBits, &gControllerStatuses[0]);
|
||||
assign_controller_data_to_port(&gControllers[0], 0);
|
||||
osContInit(&gSIEventMesgQueue, &gControllerBits, gControllerStatuses);
|
||||
|
||||
#ifdef EEP
|
||||
// strangely enough, the EEPROM probe for save data is done in this function.
|
||||
@@ -681,34 +668,43 @@ void init_controllers(void) {
|
||||
gSramProbe = nuPiInitSram();
|
||||
#endif
|
||||
|
||||
// Loop over the 4 ports and link the controller structs to the appropriate
|
||||
// status and pad. Interestingly, although there are pointers to 3 controllers,
|
||||
// only 2 are connected here. The third seems to have been reserved for debug
|
||||
// purposes and was never connected in the retail ROM, thus gPlayer3Controller
|
||||
// cannot be used, despite being referenced in various code.
|
||||
for (cont = 0, port = 0; port < 4 && cont < 2; port++) {
|
||||
// Loop over the 4 ports and link the controller structs to the appropriate status and pad.
|
||||
for (port = 0; port < MAXCONTROLLERS; port++) {
|
||||
if (cont >= MAX_NUM_PLAYERS) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Is controller plugged in?
|
||||
if (gControllerBits & (1 << port)) {
|
||||
// The game allows you to have just 1 controller plugged
|
||||
// into any port in order to play the game. this was probably
|
||||
// so if any of the ports didn't work, you can have controllers
|
||||
// plugged into any of them and it will work.
|
||||
#if ENABLE_RUMBLE
|
||||
gControllers[cont].port = port;
|
||||
assign_controller_data_to_port(&gControllers[cont], port);
|
||||
|
||||
lastUsedPort = port;
|
||||
|
||||
cont++;
|
||||
}
|
||||
}
|
||||
|
||||
#if (MAX_NUM_PLAYERS >= 2)
|
||||
//! Some flashcarts (eg. ED64p) don't let you start a ROM with a GameCube controller in port 1,
|
||||
// so if port 1 is an N64 controller and port 2 is a GC controller, swap them.
|
||||
if (
|
||||
(gEmulator & EMU_CONSOLE) &&
|
||||
((gControllerBits & 0b11) == 0b11) && // Only swap if the first two ports both have controllers plugged in.
|
||||
((gControllerStatuses[0].type & CONT_CONSOLE_MASK) == CONT_CONSOLE_N64) && // If the first port's controller is N64.
|
||||
((gControllerStatuses[1].type & CONT_CONSOLE_MASK) == CONT_CONSOLE_GCN) // If the second port's controller is GCN.
|
||||
) {
|
||||
struct Controller temp = gControllers[0];
|
||||
gControllers[0] = gControllers[1];
|
||||
gControllers[1] = temp;
|
||||
}
|
||||
#endif
|
||||
gControllers[cont].statusData = &gControllerStatuses[port];
|
||||
gControllers[cont++].controllerData = &gControllerPads[port];
|
||||
}
|
||||
}
|
||||
if ((__osControllerTypes[1] == CONT_TYPE_GCN) && (gEmulator & EMU_CONSOLE)) {
|
||||
gGamecubeControllerPort = 1;
|
||||
gPlayer1Controller = &gControllers[1];
|
||||
} else {
|
||||
if (__osControllerTypes[0] == CONT_TYPE_GCN) {
|
||||
gGamecubeControllerPort = 0;
|
||||
}
|
||||
gPlayer1Controller = &gControllers[0];
|
||||
}
|
||||
|
||||
// Disable the ports after the last used one.
|
||||
osContSetCh(lastUsedPort + 1);
|
||||
}
|
||||
|
||||
// Game thread core
|
||||
|
||||
@@ -30,9 +30,9 @@ enum ZBmodes {
|
||||
CLEAR_ZBUFFER = 1,
|
||||
};
|
||||
|
||||
extern struct Controller gControllers[3];
|
||||
extern OSContStatus gControllerStatuses[4];
|
||||
extern OSContPadEx gControllerPads[4];
|
||||
extern struct Controller gControllers[MAXCONTROLLERS];
|
||||
extern OSContStatus gControllerStatuses[MAXCONTROLLERS];
|
||||
extern OSContPadEx gControllerPads[MAXCONTROLLERS];
|
||||
extern OSMesgQueue gGameVblankQueue;
|
||||
extern OSMesgQueue gGfxVblankQueue;
|
||||
extern OSMesg gGameMesgBuf[1];
|
||||
@@ -47,7 +47,6 @@ extern Gfx *gDisplayListHead;
|
||||
extern u8 *gGfxPoolEnd;
|
||||
extern struct GfxPool *gGfxPool;
|
||||
extern u8 gControllerBits;
|
||||
extern s8 gGamecubeControllerPort;
|
||||
extern u8 gBorderHeight;
|
||||
#ifdef VANILLA_STYLE_CUSTOM_DEBUG
|
||||
extern u8 gCustomDebugMode;
|
||||
@@ -62,9 +61,10 @@ extern s8 gSramProbe;
|
||||
#endif
|
||||
|
||||
extern void (*gGoddardVblankCallback)(void);
|
||||
extern struct Controller *gPlayer1Controller;
|
||||
extern struct Controller *gPlayer2Controller;
|
||||
extern struct Controller *gPlayer3Controller;
|
||||
extern struct Controller* const gPlayer1Controller;
|
||||
extern struct Controller* const gPlayer2Controller;
|
||||
extern struct Controller* const gPlayer3Controller;
|
||||
extern struct Controller* const gPlayer4Controller;
|
||||
extern struct DemoInput *gCurrDemoInput;
|
||||
extern u16 gDemoInputListID;
|
||||
extern struct DemoInput gRecordedDemoInput;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "PR/os_internal.h"
|
||||
|
||||
#include "game_init.h"
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// Libultra structs and macros (from ultralib) //
|
||||
/////////////////////////////////////////////////
|
||||
@@ -168,7 +170,6 @@ typedef struct
|
||||
/* 0xD */ u8 r_trig;
|
||||
} __OSContGCNShortPollFormat;
|
||||
extern u8 __osContLastCmd;
|
||||
u8 __osControllerTypes[MAXCONTROLLERS];
|
||||
u8 __osGamecubeRumbleEnabled[MAXCONTROLLERS];
|
||||
|
||||
typedef struct
|
||||
@@ -216,50 +217,47 @@ void osContGetReadDataEx(OSContPadEx* data) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < __osMaxControllers; i++, data++) {
|
||||
if (__osControllerTypes[i] == CONT_TYPE_GCN) {
|
||||
if (gControllerStatuses[i].type & CONT_CONSOLE_GCN) {
|
||||
s32 stick_x, stick_y, c_stick_x, c_stick_y;
|
||||
readformatgcn = *(__OSContGCNShortPollFormat*)ptr;
|
||||
data->errno = CHNL_ERR(readformatgcn);
|
||||
if (data->errno != 0) {
|
||||
if (data->errno == 0) {
|
||||
if (!gGamecubeControllerCenters[i].initialized) {
|
||||
gGamecubeControllerCenters[i].initialized = TRUE;
|
||||
gGamecubeControllerCenters[i].stick_x = readformatgcn.stick_x;
|
||||
gGamecubeControllerCenters[i].stick_y = readformatgcn.stick_y;
|
||||
gGamecubeControllerCenters[i].c_stick_x = readformatgcn.c_stick_x;
|
||||
gGamecubeControllerCenters[i].c_stick_y = readformatgcn.c_stick_y;
|
||||
}
|
||||
|
||||
stick_x = CLAMP_S8(((s32)readformatgcn.stick_x) - gGamecubeControllerCenters[i].stick_x);
|
||||
stick_y = CLAMP_S8(((s32)readformatgcn.stick_y) - gGamecubeControllerCenters[i].stick_y);
|
||||
data->stick_x = stick_x;
|
||||
data->stick_y = stick_y;
|
||||
c_stick_x = CLAMP_S8(((s32)readformatgcn.c_stick_x) - gGamecubeControllerCenters[i].c_stick_x);
|
||||
c_stick_y = CLAMP_S8(((s32)readformatgcn.c_stick_y) - gGamecubeControllerCenters[i].c_stick_y);
|
||||
data->c_stick_x = c_stick_x;
|
||||
data->c_stick_y = c_stick_y;
|
||||
data->button = __osTranslateGCNButtons(readformatgcn.button, c_stick_x, c_stick_y);
|
||||
data->l_trig = readformatgcn.l_trig;
|
||||
data->r_trig = readformatgcn.r_trig;
|
||||
} else {
|
||||
gGamecubeControllerCenters[i].initialized = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!gGamecubeControllerCenters[i].initialized) {
|
||||
gGamecubeControllerCenters[i].initialized = TRUE;
|
||||
gGamecubeControllerCenters[i].stick_x = readformatgcn.stick_x;
|
||||
gGamecubeControllerCenters[i].stick_y = readformatgcn.stick_y;
|
||||
gGamecubeControllerCenters[i].c_stick_x = readformatgcn.c_stick_x;
|
||||
gGamecubeControllerCenters[i].c_stick_y = readformatgcn.c_stick_y;
|
||||
}
|
||||
|
||||
stick_x = CLAMP_S8(((s32)readformatgcn.stick_x) - gGamecubeControllerCenters[i].stick_x);
|
||||
stick_y = CLAMP_S8(((s32)readformatgcn.stick_y) - gGamecubeControllerCenters[i].stick_y);
|
||||
data->stick_x = stick_x;
|
||||
data->stick_y = stick_y;
|
||||
c_stick_x = CLAMP_S8(((s32)readformatgcn.c_stick_x) - gGamecubeControllerCenters[i].c_stick_x);
|
||||
c_stick_y = CLAMP_S8(((s32)readformatgcn.c_stick_y) - gGamecubeControllerCenters[i].c_stick_y);
|
||||
data->c_stick_x = c_stick_x;
|
||||
data->c_stick_y = c_stick_y;
|
||||
data->button = __osTranslateGCNButtons(readformatgcn.button, c_stick_x, c_stick_y);
|
||||
data->l_trig = readformatgcn.l_trig;
|
||||
data->r_trig = readformatgcn.r_trig;
|
||||
ptr += sizeof(__OSContGCNShortPollFormat);
|
||||
} else {
|
||||
readformat = *(__OSContReadFormat*)ptr;
|
||||
data->errno = CHNL_ERR(readformat);
|
||||
|
||||
if (data->errno != 0) {
|
||||
continue;
|
||||
if (data->errno == 0) {
|
||||
data->stick_x = readformat.stick_x;
|
||||
data->stick_y = readformat.stick_y;
|
||||
data->button = readformat.button;
|
||||
data->c_stick_x = 0;
|
||||
data->c_stick_y = 0;
|
||||
data->l_trig = 0;
|
||||
data->r_trig = 0;
|
||||
}
|
||||
|
||||
data->stick_x = readformat.stick_x;
|
||||
data->stick_y = readformat.stick_y;
|
||||
data->button = readformat.button;
|
||||
data->c_stick_x = 0;
|
||||
data->c_stick_y = 0;
|
||||
data->l_trig = 0;
|
||||
data->r_trig = 0;
|
||||
ptr += sizeof(__OSContReadFormat);
|
||||
}
|
||||
}
|
||||
@@ -295,7 +293,7 @@ static void __osPackReadData(void) {
|
||||
readformatgcn.stick_y = -1;
|
||||
|
||||
for (i = 0; i < __osMaxControllers; i++) {
|
||||
if (__osControllerTypes[i] == CONT_TYPE_GCN) {
|
||||
if (gControllerStatuses[i].type & CONT_CONSOLE_GCN) {
|
||||
readformatgcn.rumble = __osGamecubeRumbleEnabled[i];
|
||||
*(__OSContGCNShortPollFormat*)ptr = readformatgcn;
|
||||
ptr += sizeof(__OSContGCNShortPollFormat);
|
||||
@@ -379,44 +377,12 @@ extern s32 __osContinitialized;
|
||||
extern OSPifRam __osContPifRam;
|
||||
extern u8 __osContLastCmd;
|
||||
extern u8 __osMaxControllers;
|
||||
extern u8 __osControllerTypes[MAXCONTROLLERS];
|
||||
extern u8 __osGamecubeRumbleEnabled[MAXCONTROLLERS];
|
||||
|
||||
extern OSTimer __osEepromTimer;
|
||||
extern OSMesgQueue __osEepromTimerQ;
|
||||
extern OSMesg __osEepromTimerMsg;
|
||||
|
||||
// Linker script will resolve references to the original function with this one instead
|
||||
void __osContGetInitDataEx(u8* pattern, OSContStatus* data) {
|
||||
u8* ptr;
|
||||
__OSContRequesFormat requestHeader;
|
||||
s32 i;
|
||||
u8 bits;
|
||||
|
||||
bits = 0;
|
||||
ptr = (u8*)__osContPifRam.ramarray;
|
||||
for (i = 0; i < __osMaxControllers; i++, ptr += sizeof(requestHeader), data++) {
|
||||
requestHeader = *(__OSContRequesFormat*)ptr;
|
||||
data->error = CHNL_ERR(requestHeader);
|
||||
if (data->error == 0) {
|
||||
data->type = requestHeader.typel << 8 | requestHeader.typeh;
|
||||
|
||||
// Check if the input type is a gamecube controller
|
||||
// Some mupen cores seem to send back a controller type of 0xFFFF if the core doesn't initialize the input plugin quickly enough,
|
||||
// so check for that and set the input type as N64 controller if so.
|
||||
if ((data->type & CONT_GCN) && (s16)data->type != -1) {
|
||||
__osControllerTypes[i] = CONT_TYPE_GCN;
|
||||
} else {
|
||||
__osControllerTypes[i] = CONT_TYPE_N64;
|
||||
}
|
||||
|
||||
data->status = requestHeader.status;
|
||||
|
||||
bits |= 1 << i;
|
||||
}
|
||||
}
|
||||
*pattern = bits;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// motor.c //
|
||||
@@ -435,7 +401,7 @@ s32 __osMotorAccessEx(OSPfs* pfs, s32 flag) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (__osControllerTypes[pfs->channel] == CONT_TYPE_GCN) {
|
||||
if (gControllerStatuses[pfs->channel].type & CONT_CONSOLE_GCN) {
|
||||
__osGamecubeRumbleEnabled[pfs->channel] = flag;
|
||||
__osContLastCmd = CONT_CMD_END;
|
||||
} else {
|
||||
@@ -506,7 +472,7 @@ s32 osMotorInitEx(OSMesgQueue *mq, OSPfs *pfs, int channel)
|
||||
pfs->activebank = 0xFF;
|
||||
pfs->status = 0;
|
||||
|
||||
if (__osControllerTypes[pfs->channel] != CONT_TYPE_GCN) {
|
||||
if (gControllerStatuses[pfs->channel].type & CONT_CONSOLE_GCN) {
|
||||
ret = __osPfsSelectBank(pfs, 0xFE);
|
||||
|
||||
if (ret == PFS_ERR_NEW_PACK) {
|
||||
|
||||
@@ -581,11 +581,11 @@ void handle_menu_scrolling(s8 scrollDirection, s8 *currentIndex, s8 minIndex, s8
|
||||
u8 index = 0;
|
||||
|
||||
if (scrollDirection == MENU_SCROLL_VERTICAL) {
|
||||
if ((gPlayer3Controller->rawStickY > 60) || (gPlayer3Controller->buttonDown & (U_CBUTTONS | U_JPAD))) index++;
|
||||
if ((gPlayer3Controller->rawStickY < -60) || (gPlayer3Controller->buttonDown & (D_CBUTTONS | D_JPAD))) index += 2;
|
||||
if ((gPlayer1Controller->rawStickY > 60) || (gPlayer1Controller->buttonDown & (U_CBUTTONS | U_JPAD))) index++;
|
||||
if ((gPlayer1Controller->rawStickY < -60) || (gPlayer1Controller->buttonDown & (D_CBUTTONS | D_JPAD))) index += 2;
|
||||
} else if (scrollDirection == MENU_SCROLL_HORIZONTAL) {
|
||||
if ((gPlayer3Controller->rawStickX > 60) || (gPlayer3Controller->buttonDown & (R_CBUTTONS | R_JPAD))) index += 2;
|
||||
if ((gPlayer3Controller->rawStickX < -60) || (gPlayer3Controller->buttonDown & (L_CBUTTONS | L_JPAD))) index++;
|
||||
if ((gPlayer1Controller->rawStickX > 60) || (gPlayer1Controller->buttonDown & (R_CBUTTONS | R_JPAD))) index += 2;
|
||||
if ((gPlayer1Controller->rawStickX < -60) || (gPlayer1Controller->buttonDown & (L_CBUTTONS | L_JPAD))) index++;
|
||||
}
|
||||
|
||||
if (((index ^ gMenuHoldKeyIndex) & index) == 2) {
|
||||
@@ -1174,7 +1174,7 @@ void render_dialog_entries(void) {
|
||||
case DIALOG_STATE_VERTICAL:
|
||||
gDialogBoxOpenTimer = 0.0f;
|
||||
|
||||
if (gPlayer3Controller->buttonPressed & (A_BUTTON | B_BUTTON)) {
|
||||
if (gPlayer1Controller->buttonPressed & (A_BUTTON | B_BUTTON)) {
|
||||
if (gLastDialogPageStrPos == -1) {
|
||||
handle_special_dialog_text(gDialogID);
|
||||
gDialogBoxState = DIALOG_STATE_CLOSING;
|
||||
@@ -1910,7 +1910,7 @@ s32 render_pause_courses_and_castle(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gPlayer3Controller->buttonPressed & (A_BUTTON | START_BUTTON)) {
|
||||
if (gPlayer1Controller->buttonPressed & (A_BUTTON | START_BUTTON)) {
|
||||
level_set_transition(0, NULL);
|
||||
play_sound(SOUND_MENU_PAUSE_CLOSE, gGlobalSoundSource);
|
||||
gDialogBoxState = DIALOG_STATE_OPENING;
|
||||
@@ -1932,7 +1932,7 @@ s32 render_pause_courses_and_castle(void) {
|
||||
render_pause_castle_menu_box(160, 143);
|
||||
render_pause_castle_main_strings(104, 60);
|
||||
|
||||
if (gPlayer3Controller->buttonPressed & (A_BUTTON | START_BUTTON | Z_TRIG)) {
|
||||
if (gPlayer1Controller->buttonPressed & (A_BUTTON | START_BUTTON | Z_TRIG)) {
|
||||
level_set_transition(0, NULL);
|
||||
play_sound(SOUND_MENU_PAUSE_CLOSE, gGlobalSoundSource);
|
||||
gMenuMode = MENU_MODE_NONE;
|
||||
@@ -2171,7 +2171,7 @@ s32 render_course_complete_screen(void) {
|
||||
render_course_complete_lvl_info_and_hud_str();
|
||||
render_save_confirmation(100, 86, &gDialogLineNum, 20);
|
||||
|
||||
if (gCourseDoneMenuTimer > 110 && (gPlayer3Controller->buttonPressed & (A_BUTTON | START_BUTTON))) {
|
||||
if (gCourseDoneMenuTimer > 110 && (gPlayer1Controller->buttonPressed & (A_BUTTON | START_BUTTON))) {
|
||||
level_set_transition(0, NULL);
|
||||
play_sound(SOUND_MENU_STAR_SOUND, gGlobalSoundSource);
|
||||
gDialogBoxState = DIALOG_STATE_OPENING;
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "save_file.h"
|
||||
#include "sound_init.h"
|
||||
#include "rumble_init.h"
|
||||
#include "emutest.h"
|
||||
|
||||
|
||||
/**************************************************
|
||||
@@ -1712,7 +1711,10 @@ s32 execute_mario_action(UNUSED struct Object *obj) {
|
||||
|
||||
if (gMarioState->action) {
|
||||
#ifdef ENABLE_DEBUG_FREE_MOVE
|
||||
if (gPlayer1Controller->buttonDown & U_JPAD && !(gPlayer1Controller->buttonDown & L_TRIG)) {
|
||||
if (
|
||||
(gMarioState->controller->buttonDown & U_JPAD) &&
|
||||
!(gMarioState->controller->buttonDown & L_TRIG)
|
||||
) {
|
||||
set_camera_mode(gMarioState->area->camera, CAMERA_MODE_8_DIRECTIONS, 1);
|
||||
set_mario_action(gMarioState, ACT_DEBUG_FREE_MOVE, 0);
|
||||
}
|
||||
@@ -1874,12 +1876,8 @@ void init_mario_from_save_file(void) {
|
||||
gMarioState->spawnInfo = &gPlayerSpawnInfos[0];
|
||||
gMarioState->statusForCamera = &gPlayerCameraState[0];
|
||||
gMarioState->marioBodyState = &gBodyStates[0];
|
||||
gMarioState->controller = &gControllers[0];
|
||||
gMarioState->animList = &gMarioAnimsBuf;
|
||||
if ((gEmulator & EMU_CONSOLE) && __osControllerTypes[1] == CONT_TYPE_GCN) {
|
||||
gMarioState->controller = &gControllers[1];
|
||||
} else {
|
||||
gMarioState->controller = &gControllers[0];
|
||||
}
|
||||
|
||||
gMarioState->numCoins = 0;
|
||||
gMarioState->numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
|
||||
|
||||
@@ -712,12 +712,12 @@ UNUSED s32 debug_sequence_tracker(s16 debugInputSequence[]) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// If the third controller button pressed is next in sequence, reset timer and progress to next value.
|
||||
if (debugInputSequence[sDebugSequenceTracker] & gPlayer3Controller->buttonPressed) {
|
||||
// If the button pressed is next in sequence, reset timer and progress to next value.
|
||||
if (debugInputSequence[sDebugSequenceTracker] & gPlayer1Controller->buttonPressed) {
|
||||
sDebugSequenceTracker++;
|
||||
sDebugTimer = 0;
|
||||
// If wrong input or timer reaches 10, reset sequence progress.
|
||||
} else if (sDebugTimer == 10 || gPlayer3Controller->buttonPressed != 0) {
|
||||
} else if (sDebugTimer == 10 || gPlayer1Controller->buttonPressed != 0) {
|
||||
sDebugSequenceTracker = 0;
|
||||
sDebugTimer = 0;
|
||||
return FALSE;
|
||||
|
||||
@@ -1181,16 +1181,16 @@ void handle_cursor_button_input(void) {
|
||||
if (sSelectedButtonID == MENU_BUTTON_SCORE_FILE_A || sSelectedButtonID == MENU_BUTTON_SCORE_FILE_B
|
||||
|| sSelectedButtonID == MENU_BUTTON_SCORE_FILE_C
|
||||
|| sSelectedButtonID == MENU_BUTTON_SCORE_FILE_D) {
|
||||
if (gPlayer3Controller->buttonPressed & (B_BUTTON | START_BUTTON | Z_TRIG)) {
|
||||
if (gPlayer1Controller->buttonPressed & (B_BUTTON | START_BUTTON | Z_TRIG)) {
|
||||
sClickPos[0] = sCursorPos[0];
|
||||
sClickPos[1] = sCursorPos[1];
|
||||
sCursorClickingTimer = 1;
|
||||
} else if (gPlayer3Controller->buttonPressed & A_BUTTON) {
|
||||
} else if (gPlayer1Controller->buttonPressed & A_BUTTON) {
|
||||
sScoreFileCoinScoreMode = 1 - sScoreFileCoinScoreMode;
|
||||
play_sound(SOUND_MENU_CLICK_FILE_SELECT, gGlobalSoundSource);
|
||||
}
|
||||
} else { // If cursor is clicked
|
||||
if (gPlayer3Controller->buttonPressed
|
||||
if (gPlayer1Controller->buttonPressed
|
||||
& (A_BUTTON | B_BUTTON | START_BUTTON)) {
|
||||
sClickPos[0] = sCursorPos[0];
|
||||
sClickPos[1] = sCursorPos[1];
|
||||
@@ -1203,8 +1203,8 @@ void handle_cursor_button_input(void) {
|
||||
* Cursor function that handles analog stick input and button presses with a function near the end.
|
||||
*/
|
||||
void handle_controller_cursor_input(void) {
|
||||
s16 rawStickX = gPlayer3Controller->rawStickX;
|
||||
s16 rawStickY = gPlayer3Controller->rawStickY;
|
||||
s16 rawStickX = gPlayer1Controller->rawStickX;
|
||||
s16 rawStickY = gPlayer1Controller->rawStickY;
|
||||
|
||||
// Handle deadzone
|
||||
if (rawStickY > -2 && rawStickY < 2) {
|
||||
|
||||
@@ -428,7 +428,7 @@ s32 lvl_init_act_selector_values_and_stars(UNUSED s32 arg, UNUSED s32 unused) {
|
||||
s32 lvl_update_obj_and_load_act_button_actions(UNUSED s32 arg, UNUSED s32 unused) {
|
||||
if (sActSelectorMenuTimer > 10) {
|
||||
// If any of these buttons are pressed, play sound and go to course act
|
||||
if ((gPlayer3Controller->buttonPressed & (A_BUTTON | START_BUTTON | B_BUTTON | Z_TRIG))) {
|
||||
if ((gPlayer1Controller->buttonPressed & (A_BUTTON | START_BUTTON | B_BUTTON | Z_TRIG))) {
|
||||
play_sound(SOUND_MENU_STAR_SOUND_LETS_A_GO, gGlobalSoundSource);
|
||||
#if ENABLE_RUMBLE
|
||||
queue_rumble_data(60, 70);
|
||||
|
||||
@@ -110,7 +110,7 @@ s32 intro_level_select(void) {
|
||||
if (((index ^ gLevelSelectHoldKeyIndex) & index) == 2) {
|
||||
if (gCurrLevelNum > LEVEL_MAX) {
|
||||
gCurrLevelNum = LEVEL_MIN;
|
||||
} else if (gPlayer3Controller->buttonDown & B_BUTTON) {
|
||||
} else if (gPlayer1Controller->buttonDown & B_BUTTON) {
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
gCurrLevelNum += 10;
|
||||
} else {
|
||||
@@ -123,7 +123,7 @@ s32 intro_level_select(void) {
|
||||
if (gCurrLevelNum < LEVEL_MIN) {
|
||||
// Same applies to here as above
|
||||
gCurrLevelNum = LEVEL_MAX;
|
||||
} else if (gPlayer3Controller->buttonDown & B_BUTTON) {
|
||||
} else if (gPlayer1Controller->buttonDown & B_BUTTON) {
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
gCurrLevelNum -= 10;
|
||||
} else {
|
||||
@@ -187,7 +187,7 @@ s32 intro_regular(void) {
|
||||
}
|
||||
print_intro_text();
|
||||
#ifdef DEBUG_LEVEL_SELECT
|
||||
if (gPlayer3Controller->buttonDown & L_TRIG) {
|
||||
if (gPlayer1Controller->buttonDown & L_TRIG) {
|
||||
gDebugLevelSelect = TRUE;
|
||||
}
|
||||
#endif
|
||||
@@ -263,7 +263,7 @@ s32 lvl_intro_update(s16 arg, UNUSED s32 unusedArg) {
|
||||
#else
|
||||
case LVL_INTRO_REGULAR:
|
||||
#ifdef DEBUG_LEVEL_SELECT
|
||||
if (gPlayer3Controller->buttonDown & L_TRIG) {
|
||||
if (gPlayer1Controller->buttonDown & L_TRIG) {
|
||||
gDebugLevelSelect = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user