Skip to content
Open
2 changes: 1 addition & 1 deletion src/buffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ typedef struct {
extern u16 gRandomSeed16;
extern u8 randomSeedPadding[216];
extern union_D_802BFB80 D_802BFB80;
extern struct_D_802DFB80 gEncodedKartTexture[][2][8];
extern struct_D_802DFB80 gEncodedKartTexture[][4][8];

/**
* It would be nice to define gPlayerPalettesList as "struct_D_802F1F80 gPlayerPalettesList[2][4][8]".
Expand Down
2 changes: 1 addition & 1 deletion src/buffers/buffers.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/
ALIGNED8 union_D_802BFB80 D_802BFB80;
// [nothing][screen][player]
ALIGNED8 struct_D_802DFB80 gEncodedKartTexture[2][2][8];
ALIGNED8 struct_D_802DFB80 gEncodedKartTexture[2][4][8];
#ifdef AVOID_UB
// [buffer][screen][player] Buffer might be two separate buffers or something?
ALIGNED8 struct_D_802F1F80 gPlayerPalettesList[2][4][8];
Expand Down
14 changes: 8 additions & 6 deletions src/data/textures.c
Original file line number Diff line number Diff line change
Expand Up @@ -4230,21 +4230,23 @@ MenuTexture seg2_menu_2p_column[5] = {
* @brief MenuTexture for the first colone three player
*
*/
MenuTexture seg2_menu_3p_column[4] = {
MenuTexture seg2_menu_3p_column[5] = {
{ 1, texture_menu_3p_game, 64, 54, 0, 0, 0x0 },
{ 1, texture_mode_vs, 64, 18, 0, 65, 0x0 },
{ 1, texture_mode_battle, 64, 18, 0, 83, 0x0 },
{ 1, texture_mode_mario_gp, 64, 18, 0, 65, 0x0 },
{ 1, texture_mode_vs, 64, 18, 0, 83, 0x0 },
{ 1, texture_mode_battle, 64, 18, 0, 101, 0x0 },
{ 0, NULL, 0, 0, 0, 0, 0 },
};

/**
* @brief MenuTexture for the first colone four player
*
*/
MenuTexture seg2_menu_4p_column[4] = {
MenuTexture seg2_menu_4p_column[5] = {
{ 1, texture_menu_4p_game, 64, 54, 0, 0, 0x0 },
{ 1, texture_mode_vs, 64, 18, 0, 65, 0x0 },
{ 1, texture_mode_battle, 64, 18, 0, 83, 0x0 },
{ 1, texture_mode_mario_gp, 64, 18, 0, 65, 0x0 },
{ 1, texture_mode_vs, 64, 18, 0, 83, 0x0 },
{ 1, texture_mode_battle, 64, 18, 0, 101, 0x0 },
{ 0, NULL, 0, 0, 0, 0, 0 },
};

Expand Down
2 changes: 1 addition & 1 deletion src/menu_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -5414,7 +5414,7 @@ void func_8009CE64(s32 arg0) {
switch (gModeSelection) {
case 0:
case 1:
gModeSelection = 2;
gModeSelection = VERSUS;
break;
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/menus.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,31 @@ const s8 sScreenModePlayerTable[] = { SCREEN_MODE_1P, SCREEN_MODE_2P_SPLITSCREEN
const s8 sScreenModePlayerCount[] = { 1, 2, 2, 3, 4 };

// Set indexed slots numbers for one-two-three-four mode selection
const s8 gPlayerModeSelection[] = { 1, 2, 1, 1 };
const s8 gPlayerModeSelection[] = { 1, 2, 2, 2 };

// Limit for each index column in one-two-three-four mode selection
const s8 sGameModePlayerColumnDefault[][3] = {
{ 2, 1, 0 }, // 1p (GP options, TT options, ...)
{ 2, 2, 0 }, // 2p (GP options, VS options, Battle)
{ 2, 0, 0 }, // 3p (VS options, Battle, ...)
{ 2, 0, 0 }, // 4p (VS options, Battle, ...)
{ 2, 2, 0 }, // 3p (GP options, VS options, Battle, ...)
{ 2, 2, 0 }, // 4p (GP options, VS options, Battle, ...)
};

// Limit for each index column in one-two-three-four mode selection
// for extra mode (mirror mode), hence the extra value (3 instead of 2)
const s8 sGameModePlayerColumnExtra[][3] = {
{ 3, 1, 0 }, // 1p (GP options, TT options, ...)
{ 3, 3, 0 }, // 2p (GP options, VS options, Battle)
{ 3, 0, 0 }, // 3p (VS options, Battle, ...)
{ 3, 0, 0 }, // 4p (VS options, Battle, ...)
{ 3, 3, 0 }, // 3p (GP options, VS options, Battle, ...)
{ 3, 3, 0 }, // 4p (GP options, VS options, Battle, ...)
};

// Modes to select in one-two-three-four mode selection
const s32 gGameModePlayerSelection[][3] = {
{ GRAND_PRIX, TIME_TRIALS, 0x00000000 }, // 1p game modes
{ GRAND_PRIX, VERSUS, BATTLE }, // 2p game modes
{ VERSUS, BATTLE, 0x00000000 }, // 3p game modes
{ VERSUS, BATTLE, 0x00000000 }, // 4p game modes
{ GRAND_PRIX, VERSUS, BATTLE }, // 3p game modes
{ GRAND_PRIX, VERSUS, BATTLE }, // 4p game modes
};

// Map from character grid position id to character id
Expand Down
9 changes: 8 additions & 1 deletion src/player_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,14 @@ void func_80028F70(void) {
}
break;
case SCREEN_MODE_3P_4P_SPLITSCREEN:
for (size_t i = 0; i < 4; i++) {
size_t players;
if (gModeSelection == GRAND_PRIX) {
players = 8;
} else { // VERSUS, BATTLE
players = 4;
}

for (size_t i = 0; i < players; i++) {
func_80028E70(&gPlayers[i], camera1, i, 0);
}
break;
Expand Down
32 changes: 12 additions & 20 deletions src/render_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ void render_players(Camera* camera, s32 screenIdx) {
init_render_player(gPlayerTwo, camera, PLAYER_TWO, screenIdx);
init_render_player(gPlayerThree, camera, PLAYER_THREE, screenIdx);
init_render_player(gPlayerFour, camera, PLAYER_FOUR, screenIdx);
if (gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) {
if ((gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) ||
(gModeSelection == GRAND_PRIX)) {
init_render_player(gPlayerFive, camera, PLAYER_FIVE, screenIdx);
init_render_player(gPlayerSix, camera, PLAYER_SIX, screenIdx);
init_render_player(gPlayerSeven, camera, PLAYER_SEVEN, screenIdx);
Expand All @@ -371,7 +372,8 @@ void render_players(Camera* camera, s32 screenIdx) {
try_rendering_player(gPlayerTwo, PLAYER_TWO, screenIdx);
try_rendering_player(gPlayerThree, PLAYER_THREE, screenIdx);
try_rendering_player(gPlayerFour, PLAYER_FOUR, screenIdx);
if (gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) {
if ((gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) ||
(gModeSelection == GRAND_PRIX)) {
try_rendering_player(gPlayerFive, PLAYER_FIVE, screenIdx);
try_rendering_player(gPlayerSix, PLAYER_SIX, screenIdx);
try_rendering_player(gPlayerSeven, PLAYER_SEVEN, screenIdx);
Expand All @@ -384,7 +386,8 @@ void render_players(Camera* camera, s32 screenIdx) {
render_kart_particles(gPlayerTwo, PLAYER_TWO, screenIdx);
render_kart_particles(gPlayerThree, PLAYER_THREE, screenIdx);
render_kart_particles(gPlayerFour, PLAYER_FOUR, screenIdx);
if (gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) {
if ((gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) ||
(gModeSelection == GRAND_PRIX)) {
render_kart_particles(gPlayerFive, PLAYER_FIVE, screenIdx);
render_kart_particles(gPlayerSix, PLAYER_SIX, screenIdx);
render_kart_particles(gPlayerSeven, PLAYER_SEVEN, screenIdx);
Expand Down Expand Up @@ -545,7 +548,8 @@ void func_80021B0C(void) {
func_8006E7CC(gPlayerTwo, 1, 0);
func_8006E7CC(gPlayerThree, 2, 0);
func_8006E7CC(gPlayerFour, 3, 0);
if (gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) {
if ((gActiveScreenMode != SCREEN_MODE_3P_4P_SPLITSCREEN) ||
(gModeSelection == GRAND_PRIX)) {
func_8006E7CC(gPlayerFive, 4, 0);
func_8006E7CC(gPlayerSix, 5, 0);
func_8006E7CC(gPlayerSeven, 6, 0);
Expand Down Expand Up @@ -1344,17 +1348,9 @@ void render_kart(Player* player, s8 playerId, s8 screenId, s8 flipOffset) {
}
load_kart_palette(player, playerId, screenId, D_801651D0[screenId][playerId]);
gPlayerPalette = &gPlayerPalettesList[D_801651D0[screenId][playerId]][screenId][playerId];
// When screenId >= 2 (in 3/4 player mode), adjust indices to fit gEncodedKartTexture[2][2][8] dimensions
if ((screenId == 0) || (screenId == 1)) {
load_kart_texture(player, playerId, screenId, screenId, D_801651D0[screenId][playerId]);
} else {
load_kart_texture(player, playerId - 4, screenId, screenId - 1, D_801651D0[screenId][playerId]);
}
if ((screenId == 0) || (screenId == 1)) {
sKartTexture = gEncodedKartTexture[D_801651D0[screenId][playerId]][screenId][playerId].unk_00;
} else {
sKartTexture = gEncodedKartTexture[D_801651D0[screenId][playerId]][screenId - 1][playerId - 4].unk_00;
}

load_kart_texture(player, playerId, screenId, screenId, D_801651D0[screenId][playerId]);
sKartTexture = gEncodedKartTexture[D_801651D0[screenId][playerId]][screenId][playerId].unk_00;
mtxf_translate_rotate(mtx, sp154, sp14C);
mtxf_scale(mtx, gCharacterSize[player->characterId] * player->size);
convert_to_fixed_point_matrix(GetKartMatrix(playerId + (screenId * 8)), mtx);
Expand Down Expand Up @@ -1460,11 +1456,7 @@ void render_ghost(Player* player, s8 playerId, s8 screenId, s8 flipOffset) {
gPlayerPalette =
(struct_D_802F1F80*) &gPlayerPalettesList[D_801651D0[screenId][playerId]][screenId][playerId * 0x100];
#endif
if ((screenId == 0) || (screenId == 1)) {
sKartTexture = gEncodedKartTexture[D_801651D0[screenId][playerId]][screenId][playerId].unk_00;
} else {
sKartTexture = gEncodedKartTexture[D_801651D0[screenId][playerId]][screenId - 1][playerId - 4].unk_00;
}
sKartTexture = gEncodedKartTexture[D_801651D0[screenId][playerId]][screenId][playerId].unk_00;

mtxf_translate_rotate(mtx, spDC, spD4);
mtxf_scale(mtx, gCharacterSize[player->characterId] * player->size);
Expand Down
93 changes: 92 additions & 1 deletion src/spawn_players.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,84 @@ void spawn_players_2p_battle(f32* arg0, f32* arg1, f32 arg2) {
func_80039AE4();
}

// Added function
void spawn_players_gp_three_player(f32* arg0, f32* arg1, f32 arg2) {
func_80039DA4();
if ((GetCupCursorPosition() == TRACK_ONE) || (gDemoMode == 1) ||
(gDebugMenuSelection == DEBUG_MENU_OPTION_SELECTED)) {
s16 rand;
s16 i;
s16 cpuCount;

// @todo: this is a do-while loop
getRand:
rand = random_int(7);
if (gCharacterSelections[0] == rand) {
goto getRand;
}
if (gCharacterSelections[1] == rand) {
goto getRand;
}

chooseCPUPlayers[0] = rand;


if (gPlayerCountSelection1 == 3) {
cpuCount = 5;
} else { // 4 players
cpuCount = 4;
}

for (i = 1; i < cpuCount; i++) {
u16* arr = (u16*) cpu_forTwoPlayer[gCharacterSelections[0]][gCharacterSelections[1]];
if (rand == arr[i]) {
chooseCPUPlayers[i] = arr[0];
} else {
chooseCPUPlayers[i] = arr[i];
}
}
}

if (gPlayerCountSelection1 == 3) {
spawn_player(gPlayerFour, 3, arg0[D_80165270[3]], arg1[D_80165270[3]], arg2, 32768.0f, chooseCPUPlayers[0],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerFive, 4, arg0[D_80165270[4]], arg1[D_80165270[4]], arg2, 32768.0f, chooseCPUPlayers[1],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerSix, 5, arg0[D_80165270[5]], arg1[D_80165270[5]], arg2, 32768.0f, chooseCPUPlayers[2],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerSeven, 6, arg0[D_80165270[6]], arg1[D_80165270[6]], arg2, 32768.0f, chooseCPUPlayers[3],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerEight, 7, arg0[D_80165270[7]], arg1[D_80165270[7]], arg2, 32768.0f, chooseCPUPlayers[4],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerOne, 0, arg0[D_80165270[0]], arg1[D_80165270[0]], arg2, 32768.0f, gCharacterSelections[0],
PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
spawn_player(gPlayerTwo, 1, arg0[D_80165270[1]], arg1[D_80165270[1]], arg2, 32768.0f,
gCharacterSelections[1], PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
spawn_player(gPlayerThree, 2, arg0[D_80165270[2]], arg1[D_80165270[2]], arg2, 32768.0f, gCharacterSelections[2],
PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
} else { // 4 player
spawn_player(gPlayerFive, 4, arg0[D_80165270[4]], arg1[D_80165270[4]], arg2, 32768.0f, chooseCPUPlayers[0],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerSix, 5, arg0[D_80165270[5]], arg1[D_80165270[5]], arg2, 32768.0f, chooseCPUPlayers[1],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerSeven, 6, arg0[D_80165270[6]], arg1[D_80165270[6]], arg2, 32768.0f, chooseCPUPlayers[2],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerEight, 7, arg0[D_80165270[7]], arg1[D_80165270[7]], arg2, 32768.0f, chooseCPUPlayers[3],
PLAYER_EXISTS | PLAYER_CPU | PLAYER_START_SEQUENCE);
spawn_player(gPlayerOne, 0, arg0[D_80165270[0]], arg1[D_80165270[0]], arg2, 32768.0f, gCharacterSelections[0],
PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
spawn_player(gPlayerTwo, 1, arg0[D_80165270[1]], arg1[D_80165270[1]], arg2, 32768.0f, gCharacterSelections[1],
PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
spawn_player(gPlayerThree, 2, arg0[D_80165270[2]], arg1[D_80165270[2]], arg2, 32768.0f,
gCharacterSelections[2], PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
spawn_player(gPlayerFour, 3, arg0[D_80165270[3]], arg1[D_80165270[3]], arg2, 32768.0f, gCharacterSelections[3],
PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
}

D_80164A28 = 0;
func_80039AE4();
}

void func_8003B318(f32* arg0, f32* arg1, f32 arg2) {
spawn_player(gPlayerOne, 0, arg0[0], arg1[0], arg2, 32768.0f, gCharacterSelections[0],
PLAYER_EXISTS | PLAYER_START_SEQUENCE | PLAYER_HUMAN);
Expand Down Expand Up @@ -972,6 +1050,19 @@ void spawn_and_set_player_spawns(void) {

case SCREEN_MODE_3P_4P_SPLITSCREEN:
switch (gModeSelection) {
case GRAND_PRIX: // Added case to allow grand prix in 3/4 player split-screen
D_80165210[0] = (D_80165210[2] = (D_80165210[4] = (D_80165210[6] = sp5E + 0x14)));
D_80165210[1] = (D_80165210[3] = (D_80165210[5] = (D_80165210[7] = sp5E - 0x14)));
D_80165230[0] = sp5C + 0x1E;
D_80165230[1] = sp5C + 0x32;
D_80165230[2] = sp5C + 0x46;
D_80165230[3] = sp5C + 0x5A;
D_80165230[4] = sp5C + 0x6E;
D_80165230[5] = sp5C + 0x82;
D_80165230[6] = sp5C + 0x96;
D_80165230[7] = sp5C + 0xAA;
spawn_players_gp_three_player(D_80165210, D_80165230, sp5A);
break;
case VERSUS:
D_80165210[0] = sp5E + 0x1E;
D_80165210[6] = sp5E - 0xA;
Expand Down Expand Up @@ -1174,7 +1265,7 @@ void func_8003CD98(Player* player, Camera* camera, s8 playerId, s8 screenId) {
} else {
load_kart_palette(player, playerId, screenId, 0);
load_kart_palette(player, playerId, screenId, 1);
load_kart_texture(player, (s8) (playerId + 4), screenId, (s8) (screenId - 2), 0);
load_kart_texture(player, (s8) (playerId), screenId, (s8) (screenId), 0);
#ifdef TARGET_N64
mio0decode((u8*) &gEncodedKartTexture[0][screenId - 2][playerId + 4],
(u8*) &D_802BFB80.arraySize8[0][screenId - 2][playerId + 4]);
Expand Down
1 change: 1 addition & 0 deletions src/spawn_players.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ void spawn_players_versus_one_player(f32*, f32*, f32);
void spawn_players_gp_two_player(f32* arg0, f32* arg1, f32);
void spawn_players_versus_two_player(f32*, f32*, f32);
void spawn_players_2p_battle(f32*, f32*, f32);
void spawn_players_gp_three_player(f32* arg0, f32* arg1, f32 arg2);
void func_8003B318(f32*, f32*, f32);
void spawn_players_3p_battle(f32*, f32*, f32);
void func_8003B870(f32*, f32*, f32);
Expand Down
4 changes: 2 additions & 2 deletions src/textures.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,8 @@ extern MenuTexture D_02004638[2];
extern MenuTexture seg2_game_select_texture[2];
extern MenuTexture seg2_menu_1p_column[4];
extern MenuTexture seg2_menu_2p_column[5];
extern MenuTexture seg2_menu_3p_column[4];
extern MenuTexture seg2_menu_4p_column[4];
extern MenuTexture seg2_menu_3p_column[5];
extern MenuTexture seg2_menu_4p_column[5];
extern MenuTexture D_020047DC[2];
extern MenuTexture D_02004804[2];
extern MenuTexture D_0200482C[2];
Expand Down
Loading