mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 05:25:14 +00:00
Added host/join in-game GUI
Now people aren't forced to launch with command-line parameters, instead they can host or join a server by selecting buttons in the main menu.
This commit is contained in:
parent
f367ed2167
commit
68ad6bc15c
8 changed files with 291 additions and 14 deletions
|
@ -44,17 +44,13 @@ const LevelScript level_main_menu_entry_1[] = {
|
||||||
FREE_LEVEL_POOL(),
|
FREE_LEVEL_POOL(),
|
||||||
LOAD_AREA(/*area*/ 1),
|
LOAD_AREA(/*area*/ 1),
|
||||||
SET_MENU_MUSIC(/*seq*/ 0x0021),
|
SET_MENU_MUSIC(/*seq*/ 0x0021),
|
||||||
#ifndef IMMEDIATELOAD
|
|
||||||
TRANSITION(/*transType*/ WARP_TRANSITION_FADE_FROM_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
TRANSITION(/*transType*/ WARP_TRANSITION_FADE_FROM_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
||||||
#endif
|
|
||||||
CALL(/*arg*/ 0, /*func*/ lvl_init_menu_values_and_cursor_pos),
|
CALL(/*arg*/ 0, /*func*/ lvl_init_menu_values_and_cursor_pos),
|
||||||
CALL_LOOP(/*arg*/ 0, /*func*/ lvl_update_obj_and_load_file_selected),
|
CALL_LOOP(/*arg*/ 0, /*func*/ lvl_update_obj_and_load_file_selected),
|
||||||
GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_SAVE_FILE_NUM),
|
GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_SAVE_FILE_NUM),
|
||||||
STOP_MUSIC(/*fadeOutTime*/ 0x00BE),
|
STOP_MUSIC(/*fadeOutTime*/ 0x00BE),
|
||||||
#ifndef IMMEDIATELOAD
|
|
||||||
TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
||||||
SLEEP(/*frames*/ 16),
|
SLEEP(/*frames*/ 16),
|
||||||
#endif
|
|
||||||
CLEAR_LEVEL(),
|
CLEAR_LEVEL(),
|
||||||
SLEEP_BEFORE_EXIT(/*frames*/ 1),
|
SLEEP_BEFORE_EXIT(/*frames*/ 1),
|
||||||
SET_REG(/*value*/ LEVEL_CASTLE_GROUNDS),
|
SET_REG(/*value*/ LEVEL_CASTLE_GROUNDS),
|
||||||
|
|
|
@ -411,6 +411,36 @@ void render_multi_text_string(s16 *xPos, s16 *yPos, s8 multiTextID)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void str_ascii_to_dialog(char* string, char* dialog, int length) {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
switch (string[i]) {
|
||||||
|
case '\'': dialog[i] = 0x3E; break;
|
||||||
|
case '.': dialog[i] = 0x3F; break;
|
||||||
|
case ',': dialog[i] = DIALOG_CHAR_COMMA; break;
|
||||||
|
case '-': dialog[i] = 0x9F; break;
|
||||||
|
case '(': dialog[i] = 0xE1; break;
|
||||||
|
case ')': dialog[i] = 0xE3; break;
|
||||||
|
case '&': dialog[i] = 0xE5; break;
|
||||||
|
case '!': dialog[i] = 0xF2; break;
|
||||||
|
case '%': dialog[i] = 0xF3; break;
|
||||||
|
case '?': dialog[i] = 0xF4; break;
|
||||||
|
case '"': dialog[i] = 0xF6; break; // 0xF5 is opening quote
|
||||||
|
case '~': dialog[i] = 0xF7; break;
|
||||||
|
case '*': dialog[i] = 0xFB; break;
|
||||||
|
case ' ': dialog[i] = DIALOG_CHAR_SPACE; break;
|
||||||
|
case '\n': dialog[i] = DIALOG_CHAR_NEWLINE; break;
|
||||||
|
default: dialog[i] = ASCII_TO_DIALOG(string[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialog[length] = DIALOG_CHAR_TERMINATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_generic_ascii_string(s16 x, s16 y, const u8* ascii) {
|
||||||
|
u8 dialog[256] = { DIALOG_CHAR_TERMINATOR };
|
||||||
|
str_ascii_to_dialog(ascii, dialog, strlen(ascii));
|
||||||
|
print_generic_string(x, y, dialog);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(VERSION_JP) || defined(VERSION_SH)
|
#if defined(VERSION_JP) || defined(VERSION_SH)
|
||||||
#define MAX_STRING_WIDTH 18
|
#define MAX_STRING_WIDTH 18
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
((asc) >= 'A' && (asc) <= 'Z') ? ((asc) - 'A' + 0x0A) : \
|
((asc) >= 'A' && (asc) <= 'Z') ? ((asc) - 'A' + 0x0A) : \
|
||||||
((asc) >= 'a' && (asc) <= 'z') ? ((asc) - 'a' + 0x24) : 0x00)
|
((asc) >= 'a' && (asc) <= 'z') ? ((asc) - 'a' + 0x24) : 0x00)
|
||||||
|
|
||||||
|
|
||||||
#define MENU_MTX_PUSH 1
|
#define MENU_MTX_PUSH 1
|
||||||
#define MENU_MTX_NOPUSH 2
|
#define MENU_MTX_NOPUSH 2
|
||||||
|
|
||||||
|
@ -117,6 +116,8 @@ extern s8 gRedCoinsCollected;
|
||||||
void create_dl_identity_matrix(void);
|
void create_dl_identity_matrix(void);
|
||||||
void create_dl_translation_matrix(s8 pushOp, f32 x, f32 y, f32 z);
|
void create_dl_translation_matrix(s8 pushOp, f32 x, f32 y, f32 z);
|
||||||
void create_dl_ortho_matrix(void);
|
void create_dl_ortho_matrix(void);
|
||||||
|
void str_ascii_to_dialog(char* string, char* dialog, int length);
|
||||||
|
void print_generic_ascii_string(s16 x, s16 y, const u8* ascii);
|
||||||
void print_generic_string(s16 x, s16 y, const u8 *str);
|
void print_generic_string(s16 x, s16 y, const u8 *str);
|
||||||
void print_hud_lut_string(s8 hudLUT, s16 x, s16 y, const u8 *str);
|
void print_hud_lut_string(s8 hudLUT, s16 x, s16 y, const u8 *str);
|
||||||
void print_menu_generic_string(s16 x, s16 y, const u8 *str);
|
void print_menu_generic_string(s16 x, s16 y, const u8 *str);
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#include "sm64.h"
|
#include "sm64.h"
|
||||||
#include "text_strings.h"
|
#include "text_strings.h"
|
||||||
|
|
||||||
|
#include "pc/controller/controller_keyboard.h"
|
||||||
|
#include "pc/network/network.h"
|
||||||
|
|
||||||
#include "eu_translation.h"
|
#include "eu_translation.h"
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
#undef LANGUAGE_FUNCTION
|
#undef LANGUAGE_FUNCTION
|
||||||
|
@ -52,7 +55,7 @@ static s16 sSoundTextY;
|
||||||
#define NUM_BUTTONS 34
|
#define NUM_BUTTONS 34
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define NUM_BUTTONS 32
|
#define NUM_BUTTONS 36
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Amount of main menu buttons defined in the code called by spawn_object_rel_with_rot.
|
// Amount of main menu buttons defined in the code called by spawn_object_rel_with_rot.
|
||||||
|
@ -372,6 +375,12 @@ static void bhv_menu_button_growing_from_main_menu(struct Object *button) {
|
||||||
* Shrink back to main menu, used to return back while inside menus.
|
* Shrink back to main menu, used to return back while inside menus.
|
||||||
*/
|
*/
|
||||||
static void bhv_menu_button_shrinking_to_main_menu(struct Object *button) {
|
static void bhv_menu_button_shrinking_to_main_menu(struct Object *button) {
|
||||||
|
// hack, make sure network button goes off-screen
|
||||||
|
if (button == sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]) {
|
||||||
|
button->oMenuButtonOrigPosX = 0;
|
||||||
|
button->oMenuButtonOrigPosY = -9999;
|
||||||
|
}
|
||||||
|
|
||||||
if (button->oMenuButtonTimer < 16) {
|
if (button->oMenuButtonTimer < 16) {
|
||||||
button->oFaceAngleYaw -= 0x800;
|
button->oFaceAngleYaw -= 0x800;
|
||||||
}
|
}
|
||||||
|
@ -1022,14 +1031,17 @@ void render_sound_mode_menu_buttons(struct Object *soundModeButton) {
|
||||||
sMainMenuButtons[MENU_BUTTON_STEREO] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_STEREO] = spawn_object_rel_with_rot(
|
||||||
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_STEREO]->oMenuButtonScale = 0.11111111f;
|
sMainMenuButtons[MENU_BUTTON_STEREO]->oMenuButtonScale = 0.11111111f;
|
||||||
|
sMainMenuButtons[MENU_BUTTON_STEREO]->oFaceAngleRoll = 0;
|
||||||
// Mono option button
|
// Mono option button
|
||||||
sMainMenuButtons[MENU_BUTTON_MONO] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_MONO] = spawn_object_rel_with_rot(
|
||||||
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 0, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 0, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_MONO]->oMenuButtonScale = 0.11111111f;
|
sMainMenuButtons[MENU_BUTTON_MONO]->oMenuButtonScale = 0.11111111f;
|
||||||
|
sMainMenuButtons[MENU_BUTTON_MONO]->oFaceAngleRoll = 0;
|
||||||
// Headset option button
|
// Headset option button
|
||||||
sMainMenuButtons[MENU_BUTTON_HEADSET] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_HEADSET] = spawn_object_rel_with_rot(
|
||||||
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, -533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, -533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_HEADSET]->oMenuButtonScale = 0.11111111f;
|
sMainMenuButtons[MENU_BUTTON_HEADSET]->oMenuButtonScale = 0.11111111f;
|
||||||
|
sMainMenuButtons[MENU_BUTTON_HEADSET]->oFaceAngleRoll = 0;
|
||||||
|
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
// English option button
|
// English option button
|
||||||
|
@ -1115,13 +1127,10 @@ void check_sound_mode_menu_clicked_buttons(struct Object *soundModeButton) {
|
||||||
* retuning sSelectedFileNum to a save value defined in fileNum.
|
* retuning sSelectedFileNum to a save value defined in fileNum.
|
||||||
*/
|
*/
|
||||||
void load_main_menu_save_file(struct Object *fileButton, s32 fileNum) {
|
void load_main_menu_save_file(struct Object *fileButton, s32 fileNum) {
|
||||||
#ifdef IMMEDIATELOAD
|
|
||||||
sSelectedFileNum = fileNum;
|
|
||||||
#else
|
|
||||||
if (fileButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) {
|
if (fileButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) {
|
||||||
sSelectedFileNum = fileNum;
|
sSelectedFileNum = fileNum;
|
||||||
|
network_init(NT_SERVER, "", NETWORK_DEFAULT_PORT);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1162,6 +1171,11 @@ void return_to_main_menu(s16 prevMenuButtonID, struct Object *sourceButton) {
|
||||||
mark_obj_for_deletion(sMainMenuButtons[buttonID]);
|
mark_obj_for_deletion(sMainMenuButtons[buttonID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (prevMenuButtonID == MENU_BUTTON_NETWORK_MODE) {
|
||||||
|
for (buttonID = MENU_BUTTON_NETWORK_MIN; buttonID < MENU_BUTTON_NETWORK_MAX; buttonID++) {
|
||||||
|
mark_obj_for_deletion(sMainMenuButtons[buttonID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,6 +1367,10 @@ void bhv_menu_button_manager_init(void) {
|
||||||
sMainMenuButtons[MENU_BUTTON_SOUND_MODE] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_SOUND_MODE] = spawn_object_rel_with_rot(
|
||||||
gCurrentObject, MODEL_MAIN_MENU_PURPLE_SOUND_BUTTON, bhvMenuButton, 6400, -3500, 0, 0, 0, 0);
|
gCurrentObject, MODEL_MAIN_MENU_PURPLE_SOUND_BUTTON, bhvMenuButton, 6400, -3500, 0, 0, 0, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonScale = 1.0f;
|
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonScale = 1.0f;
|
||||||
|
// Network menu button
|
||||||
|
sMainMenuButtons[MENU_BUTTON_NETWORK_MODE] = spawn_object_rel_with_rot(
|
||||||
|
gCurrentObject, MODEL_MAIN_MENU_GREEN_SCORE_BUTTON, bhvMenuButton, 6400, -5500, 0, 0, 0, 0);
|
||||||
|
sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]->oMenuButtonScale = 1.0f;
|
||||||
|
|
||||||
sTextBaseAlpha = 0;
|
sTextBaseAlpha = 0;
|
||||||
}
|
}
|
||||||
|
@ -1368,6 +1386,30 @@ void bhv_menu_button_manager_init(void) {
|
||||||
* Also play a sound and/or render buttons depending of the button ID selected.
|
* Also play a sound and/or render buttons depending of the button ID selected.
|
||||||
*/
|
*/
|
||||||
void check_main_menu_clicked_buttons(void) {
|
void check_main_menu_clicked_buttons(void) {
|
||||||
|
|
||||||
|
// force the network screen to open automatically
|
||||||
|
static u8 networkInit = FALSE;
|
||||||
|
if (!networkInit) {
|
||||||
|
sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
|
||||||
|
|
||||||
|
struct Object* button = sMainMenuButtons[MENU_BUTTON_NETWORK_MODE];
|
||||||
|
button->oFaceAnglePitch = 0;
|
||||||
|
button->oFaceAngleYaw = 32768;
|
||||||
|
button->oFaceAngleRoll = 0;
|
||||||
|
button->oParentRelativePosX = 0.0f;
|
||||||
|
button->oParentRelativePosY = 0.0f;
|
||||||
|
button->oParentRelativePosZ = 17800.0f;
|
||||||
|
button->oMenuButtonOrigPosX = 0;
|
||||||
|
button->oMenuButtonOrigPosY = 0;
|
||||||
|
button->oMenuButtonOrigPosZ = -17800.0f;
|
||||||
|
button->oMenuButtonScale = 1.0f;
|
||||||
|
button->oMenuButtonState = MENU_BUTTON_STATE_FULLSCREEN;
|
||||||
|
button->oMenuButtonTimer = 0;
|
||||||
|
|
||||||
|
sSelectedButtonID = MENU_BUTTON_NETWORK_MODE;
|
||||||
|
networkInit = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
if (sMainMenuTimer >= 5) {
|
if (sMainMenuTimer >= 5) {
|
||||||
#endif
|
#endif
|
||||||
|
@ -1433,6 +1475,10 @@ void check_main_menu_clicked_buttons(void) {
|
||||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||||
render_sound_mode_menu_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
render_sound_mode_menu_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
||||||
break;
|
break;
|
||||||
|
case MENU_BUTTON_NETWORK_MODE:
|
||||||
|
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||||
|
render_network_mode_menu_buttons(sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
}
|
}
|
||||||
|
@ -1541,6 +1587,17 @@ void bhv_menu_button_manager_loop(void) {
|
||||||
check_sound_mode_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
check_sound_mode_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MENU_BUTTON_NETWORK_MODE:
|
||||||
|
check_network_mode_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MENU_BUTTON_HOST:
|
||||||
|
return_to_main_menu(MENU_BUTTON_NETWORK_MODE, sMainMenuButtons[MENU_BUTTON_HOST]);
|
||||||
|
break;
|
||||||
|
case MENU_BUTTON_JOIN:
|
||||||
|
exit_join_to_network_menu();
|
||||||
|
break;
|
||||||
|
|
||||||
// STEREO, MONO and HEADSET buttons are undefined so they can be selected without
|
// STEREO, MONO and HEADSET buttons are undefined so they can be selected without
|
||||||
// exiting the Options menu, as a result they added a return button
|
// exiting the Options menu, as a result they added a return button
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
|
@ -1597,11 +1654,16 @@ void handle_cursor_button_input(void) {
|
||||||
sClickPos[1] = sCursorPos[1];
|
sClickPos[1] = sCursorPos[1];
|
||||||
sCursorClickingTimer = 1;
|
sCursorClickingTimer = 1;
|
||||||
}
|
}
|
||||||
#ifdef IMMEDIATELOAD
|
if (networkType == NT_SERVER) {
|
||||||
|
sClickPos[0] = sCursorPos[0];
|
||||||
|
sClickPos[1] = sCursorPos[1];
|
||||||
|
sCursorClickingTimer = 1;
|
||||||
|
}
|
||||||
|
/*#ifdef IMMEDIATELOAD
|
||||||
sClickPos[0] = sCursorPos[0];
|
sClickPos[0] = sCursorPos[0];
|
||||||
sClickPos[1] = sCursorPos[1];
|
sClickPos[1] = sCursorPos[1];
|
||||||
sCursorClickingTimer = 1;
|
sCursorClickingTimer = 1;
|
||||||
#endif
|
#endif*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2758,6 +2820,12 @@ static void print_file_select_strings(void) {
|
||||||
case MENU_BUTTON_SOUND_MODE:
|
case MENU_BUTTON_SOUND_MODE:
|
||||||
print_sound_mode_menu_strings();
|
print_sound_mode_menu_strings();
|
||||||
break;
|
break;
|
||||||
|
case MENU_BUTTON_NETWORK_MODE:
|
||||||
|
print_network_mode_menu_strings();
|
||||||
|
break;
|
||||||
|
case MENU_BUTTON_JOIN:
|
||||||
|
print_join_mode_menu_strings();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// If all 4 save file exists, define true to sAllFilesExist to prevent more copies in copy menu
|
// If all 4 save file exists, define true to sAllFilesExist to prevent more copies in copy menu
|
||||||
if (save_file_exists(SAVE_FILE_A) == TRUE && save_file_exists(SAVE_FILE_B) == TRUE &&
|
if (save_file_exists(SAVE_FILE_A) == TRUE && save_file_exists(SAVE_FILE_B) == TRUE &&
|
||||||
|
@ -2842,6 +2910,16 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// center cursor
|
||||||
|
sCursorPos[0] = 0.0f;
|
||||||
|
sCursorPos[1] = -24.0f;
|
||||||
|
|
||||||
|
// immediately jump in
|
||||||
|
if (networkType != NT_NONE) {
|
||||||
|
sSelectedFileNum = 1;
|
||||||
|
}
|
||||||
|
|
||||||
//! no return value
|
//! no return value
|
||||||
#ifdef AVOID_UB
|
#ifdef AVOID_UB
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2857,3 +2935,164 @@ s32 lvl_update_obj_and_load_file_selected(UNUSED s32 arg, UNUSED s32 unused) {
|
||||||
area_update_objects();
|
area_update_objects();
|
||||||
return sSelectedFileNum;
|
return sSelectedFileNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- custom network menu code --- //
|
||||||
|
|
||||||
|
void exit_join_to_network_menu(void) {
|
||||||
|
// Begin exit
|
||||||
|
if (sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN
|
||||||
|
&& sCursorClickingTimer == 2) {
|
||||||
|
play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs);
|
||||||
|
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING;
|
||||||
|
keyboard_stop_text_input();
|
||||||
|
}
|
||||||
|
// End exit
|
||||||
|
if (sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT) {
|
||||||
|
sSelectedButtonID = MENU_BUTTON_NETWORK_MODE;
|
||||||
|
if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) {
|
||||||
|
sCurrentMenuLevel = MENU_LAYER_MAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_exit_join_to_network_menu(void) {
|
||||||
|
sCursorClickingTimer = 2;
|
||||||
|
exit_join_to_network_menu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void join_server_as_client(void) {
|
||||||
|
sCursorClickingTimer = 2;
|
||||||
|
char delims[] = { ' ' };
|
||||||
|
|
||||||
|
// trim whitespace
|
||||||
|
char* text = textInput;
|
||||||
|
while (*text == ' ') { text++; }
|
||||||
|
|
||||||
|
// grab IP
|
||||||
|
char* ip = strtok(text, delims);
|
||||||
|
if (ip == NULL) {
|
||||||
|
exit_join_to_network_menu();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab port
|
||||||
|
char* port = strtok(NULL, delims);
|
||||||
|
if (port != NULL && atoi(port) == 0) {
|
||||||
|
exit_join_to_network_menu();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
network_init(NT_CLIENT, textInput, port);
|
||||||
|
sSelectedFileNum = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_network_mode_menu_buttons(struct Object* soundModeButton) {
|
||||||
|
#define NETWORK_BUTTON_Y 0
|
||||||
|
// Host option button
|
||||||
|
sMainMenuButtons[MENU_BUTTON_HOST] = spawn_object_rel_with_rot(
|
||||||
|
soundModeButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 266, NETWORK_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
|
sMainMenuButtons[MENU_BUTTON_HOST]->oMenuButtonScale = 0.11111111f;
|
||||||
|
sMainMenuButtons[MENU_BUTTON_HOST]->oFaceAngleRoll = 0;
|
||||||
|
|
||||||
|
// Join option button
|
||||||
|
sMainMenuButtons[MENU_BUTTON_JOIN] = spawn_object_rel_with_rot(
|
||||||
|
soundModeButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -266, NETWORK_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
|
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonScale = 0.11111111f;
|
||||||
|
sMainMenuButtons[MENU_BUTTON_JOIN]->oFaceAngleRoll = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_network_mode_menu_clicked_buttons(struct Object* networkModeButton) {
|
||||||
|
if (networkModeButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) {
|
||||||
|
s32 buttonID;
|
||||||
|
// Configure sound mode menu button group
|
||||||
|
for (buttonID = MENU_BUTTON_NETWORK_MIN; buttonID < MENU_BUTTON_NETWORK_MAX; buttonID++) {
|
||||||
|
s16 buttonX = sMainMenuButtons[buttonID]->oPosX;
|
||||||
|
s16 buttonY = sMainMenuButtons[buttonID]->oPosY;
|
||||||
|
|
||||||
|
if (check_clicked_button(buttonX, buttonY, 22.0f) == TRUE) {
|
||||||
|
if (buttonID == MENU_BUTTON_HOST) {
|
||||||
|
if (networkModeButton->oMenuButtonActionPhase == SOUND_MODE_PHASE_MAIN) {
|
||||||
|
play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs);
|
||||||
|
sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT;
|
||||||
|
sSelectedButtonID = buttonID;
|
||||||
|
//sSoundMode = buttonID - MENU_BUTTON_OPTION_MIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (buttonID == MENU_BUTTON_JOIN) {
|
||||||
|
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||||
|
sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
|
||||||
|
sSelectedButtonID = buttonID;
|
||||||
|
keyboard_start_text_input(TIM_IP, keyboard_exit_join_to_network_menu, join_server_as_client);
|
||||||
|
}
|
||||||
|
sCurrentMenuLevel = MENU_LAYER_SUBMENU;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_network_mode_menu_strings(void) {
|
||||||
|
s32 mode;
|
||||||
|
s16 textX;
|
||||||
|
#define HEADER_HUD_X 106
|
||||||
|
unsigned char textHeader[10];
|
||||||
|
str_ascii_to_dialog("SM64 COOP", textHeader, 9);
|
||||||
|
|
||||||
|
// Print header text
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
||||||
|
|
||||||
|
print_hud_lut_string(HUD_LUT_DIFF, HEADER_HUD_X, 35, textHeader);
|
||||||
|
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
||||||
|
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||||
|
|
||||||
|
#define TEXT_HOST 0x11,0x18,0x1C,0x1D,0xFF
|
||||||
|
#define TEXT_JOIN 0x13,0x18,0x12,0x17,0xFF
|
||||||
|
static unsigned char textNetworkModes[][5] = { { TEXT_HOST }, { TEXT_JOIN } };
|
||||||
|
|
||||||
|
// Print network mode names
|
||||||
|
for (mode = 0; mode < 2; mode++) {
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
||||||
|
|
||||||
|
textX = get_str_x_pos_from_center(mode * 72 + 124, textNetworkModes[mode], 10.0f);
|
||||||
|
print_generic_string(textX, 87, textNetworkModes[mode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_join_mode_menu_strings(void) {
|
||||||
|
#define JOIN_MARIO_X 25
|
||||||
|
#define JOIN_FILE_LETTER_X 95
|
||||||
|
#define JOIN_LEVEL_NAME_X 25
|
||||||
|
#define JOIN_SECRET_STARS_X 171
|
||||||
|
#define JOIN_MYSCORE_X 238
|
||||||
|
#define JOIN_HISCORE_X 231
|
||||||
|
|
||||||
|
unsigned char textMario[8];
|
||||||
|
str_ascii_to_dialog("CONNECT", textMario, 7);
|
||||||
|
|
||||||
|
void** levelNameTable = segmented_to_virtual(seg2_course_name_table);
|
||||||
|
|
||||||
|
// Print file name at top
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
||||||
|
print_hud_lut_string(HUD_LUT_DIFF, JOIN_MARIO_X, 15, textMario);
|
||||||
|
|
||||||
|
// Print course scores
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin);
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
||||||
|
|
||||||
|
// Print level name
|
||||||
|
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 0), "Type or paste the host's IP.");
|
||||||
|
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 2), textInput);
|
||||||
|
|
||||||
|
if (strlen(textInput) > 0) {
|
||||||
|
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Press (ENTER) to join.");
|
||||||
|
}
|
||||||
|
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end);
|
||||||
|
}
|
||||||
|
|
|
@ -87,7 +87,14 @@ enum MenuButtonTypes {
|
||||||
MENU_BUTTON_LANGUAGE_RETURN,
|
MENU_BUTTON_LANGUAGE_RETURN,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MENU_BUTTON_OPTION_MAX
|
MENU_BUTTON_OPTION_MAX,
|
||||||
|
|
||||||
|
MENU_BUTTON_NETWORK_MODE,
|
||||||
|
MENU_BUTTON_NETWORK_MIN,
|
||||||
|
MENU_BUTTON_HOST = MENU_BUTTON_NETWORK_MIN,
|
||||||
|
MENU_BUTTON_JOIN,
|
||||||
|
MENU_BUTTON_NETWORK_MAX,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ScoreMenuMessageID {
|
enum ScoreMenuMessageID {
|
||||||
|
|
|
@ -16,6 +16,9 @@ void network_init(enum NetworkType inNetworkType, char* ip, char* port) {
|
||||||
networkType = inNetworkType;
|
networkType = inNetworkType;
|
||||||
|
|
||||||
if (networkType == NT_NONE) { return; }
|
if (networkType == NT_NONE) { return; }
|
||||||
|
if (port == NULL) {
|
||||||
|
port = NETWORK_DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a receiver socket to receive datagrams
|
// Create a receiver socket to receive datagrams
|
||||||
gSocket = socket_initialize();
|
gSocket = socket_initialize();
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define MAX_SYNC_OBJECT_FIELDS 64
|
#define MAX_SYNC_OBJECT_FIELDS 64
|
||||||
#define PACKET_LENGTH 1024
|
#define PACKET_LENGTH 1024
|
||||||
#define NETWORKTYPESTR (networkType == NT_CLIENT ? "Client" : "Server")
|
#define NETWORKTYPESTR (networkType == NT_CLIENT ? "Client" : "Server")
|
||||||
|
#define NETWORK_DEFAULT_PORT "7777"
|
||||||
|
|
||||||
enum PacketType {
|
enum PacketType {
|
||||||
PACKET_ACK,
|
PACKET_ACK,
|
||||||
|
|
|
@ -243,7 +243,7 @@ void main_func(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char window_title[96] =
|
char window_title[96] =
|
||||||
"Super Mario 64 coop EX (" RAPI_NAME ")"
|
"Super Mario 64 EX coop (" RAPI_NAME ")"
|
||||||
#ifdef NIGHTLY
|
#ifdef NIGHTLY
|
||||||
" nightly " GIT_HASH
|
" nightly " GIT_HASH
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue