mirror of
https://github.com/AloUltraExt/sm64ex-alo.git
synced 2025-01-22 15:43:42 -05:00
QOL Redone: Zelda style level select
This commit is contained in:
parent
529ab3e494
commit
81891375ca
9 changed files with 315 additions and 2 deletions
|
@ -19,6 +19,11 @@
|
|||
#define HAS_FRAMEBUFFER 0
|
||||
#endif
|
||||
|
||||
// --| Quality of life redone files
|
||||
/// Adds Zelda level select used on OOT, MM and Animal Forest
|
||||
/// Credits: (AloXado320)
|
||||
#define ZELDA_STYLE_LEVEL_SELECT (0 || QOL_REDONE)
|
||||
|
||||
// --| Quality of life features
|
||||
/// Adds an extra Z button trig for some menu files (Originally defined in EU)
|
||||
/// Credits: (Original Devs)
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#include "game/paintings.h"
|
||||
#include "menu/debug_level_select.h"
|
||||
#include "menu/intro_geo.h"
|
||||
#if ZELDA_STYLE_LEVEL_SELECT
|
||||
#include "menu/title_screen.h"
|
||||
#endif
|
||||
|
||||
#include "make_const_nonconst.h"
|
||||
|
||||
|
@ -146,6 +149,7 @@ const GeoLayout intro_geo_000414[] = {
|
|||
GEO_CAMERA_FRUSTUM(45, 128, 16384),
|
||||
GEO_OPEN_NODE(),
|
||||
GEO_CAMERA(0, 0, 0, 1200, 0, 0, 0, 0x00000000),
|
||||
#if !ZELDA_STYLE_LEVEL_SELECT
|
||||
GEO_OPEN_NODE(),
|
||||
GEO_TRANSLATE_NODE_WITH_DL(LAYER_OPAQUE, -230, 300, 0, debug_level_select_dl_07000858),
|
||||
GEO_TRANSLATE_NODE_WITH_DL(LAYER_OPAQUE, -120, 300, 0, debug_level_select_dl_07001100),
|
||||
|
@ -158,8 +162,15 @@ const GeoLayout intro_geo_000414[] = {
|
|||
GEO_TRANSLATE_NODE_WITH_DL(LAYER_OPAQUE, 180, 100, 0, debug_level_select_dl_070059F8),
|
||||
GEO_TRANSLATE_NODE_WITH_DL(LAYER_OPAQUE, 300, 100, 0, debug_level_select_dl_070063B0),
|
||||
GEO_CLOSE_NODE(),
|
||||
#endif
|
||||
GEO_CLOSE_NODE(),
|
||||
GEO_CLOSE_NODE(),
|
||||
#if ZELDA_STYLE_LEVEL_SELECT
|
||||
GEO_ZBUFFER(0),
|
||||
GEO_OPEN_NODE(),
|
||||
GEO_ASM(0, geo_debug_level_select_strings),
|
||||
GEO_CLOSE_NODE(),
|
||||
#endif
|
||||
GEO_CLOSE_NODE(),
|
||||
GEO_END(),
|
||||
};
|
||||
|
|
|
@ -154,6 +154,9 @@ const LevelScript level_intro_entry_4[] = {
|
|||
FIXED_LOAD(/*loadAddr*/ _goddardSegmentStart, /*romStart*/ _goddardSegmentRomStart, /*romEnd*/ _goddardSegmentRomEnd),
|
||||
#endif
|
||||
ALLOC_LEVEL_POOL(),
|
||||
#if ZELDA_STYLE_LEVEL_SELECT
|
||||
CALL(/*arg*/ 0, /*func*/ lvl_init_intro_level_select),
|
||||
#endif
|
||||
|
||||
AREA(/*index*/ 1, intro_geo_000414),
|
||||
END_AREA(),
|
||||
|
|
|
@ -195,7 +195,7 @@ s16 get_str_x_pos_from_center_custom_ascii(s16 lutType, s16 centerPos, char *str
|
|||
|
||||
// return the x position of where the string starts as half the string's
|
||||
// length from the position of the provided center.
|
||||
return (centerPos - (spacesWidth / scale));
|
||||
return (centerPos - (spacesWidth / 2.0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,9 @@ s16 get_hud_str_width(u8 *str);
|
|||
s16 get_hud_str_width_ascii(char *str);
|
||||
s16 get_string_width_ascii(char *str);
|
||||
|
||||
s16 get_str_x_pos_from_center_custom_hex(s16 lutType, s16 centerPos, u8 *strHex, u8 useScale, f32 scale);
|
||||
s16 get_str_x_pos_from_center_custom_ascii(s16 lutType, s16 centerPos, char *strAscii, u8 useScale, f32 scale);
|
||||
|
||||
void print_generic_string_ascii(s16 x, s16 y, const char *str);
|
||||
void print_generic_string_detail(s16 x, s16 y, u8 *text, u8 r, u8 g, u8 b, u8 a, s8 hasShadow, s8 shadowPad);
|
||||
void print_generic_string_ascii_detail(s16 x, s16 y, const char *str, u8 r, u8 g, u8 b, u8 a, s8 hasShadow, s8 shadowPad);
|
||||
|
|
276
src/extras/redone/title_screen.inc.c
Normal file
276
src/extras/redone/title_screen.inc.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Redone description:
|
||||
* A backported version of the level select used in Zelda-engine games released on N64.
|
||||
* Adapted to Super Mario 64 by AloXado320, replaces old debug level select.
|
||||
* Props to ZeldaRET for decompiling the code (z_select.c).
|
||||
*/
|
||||
|
||||
#include "game/segment2.h"
|
||||
#include "game/ingame_menu.h"
|
||||
#include "extras/draw_util.h"
|
||||
|
||||
#define MAX_PAGE_STRINGS 16
|
||||
#define PAGE_DOWN_STOPS_MAX (LEVEL_MAX / MAX_PAGE_STRINGS)
|
||||
|
||||
struct ZDebugLevelSelect {
|
||||
s32 count;
|
||||
s32 currentScene;
|
||||
s32 pageDownIndex; // Index of pageDownStops
|
||||
s32 pageDownStops[PAGE_DOWN_STOPS_MAX];
|
||||
s32 topDisplayedScene; // The scene which is currently at the top of the screen
|
||||
s32 verticalInputAccumulator;
|
||||
s32 verticalInput;
|
||||
s32 timerUp;
|
||||
s32 timerDown;
|
||||
s32 lockUp;
|
||||
s32 lockDown;
|
||||
s32 refreshRate;
|
||||
};
|
||||
|
||||
// Duplicate copy to initiate struct
|
||||
struct ZDebugLevelSelect gZDbgLevelSelectInit;
|
||||
struct ZDebugLevelSelect *gZDbgLevelSelect = &gZDbgLevelSelectInit;
|
||||
|
||||
void print_debug_level_select_menu(struct ZDebugLevelSelect *this) {
|
||||
s32 scene;
|
||||
s32 i;
|
||||
char *name;
|
||||
s32 xPos;
|
||||
char *chrTemp;
|
||||
u8 strScene[4];
|
||||
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 155, 150, 255);
|
||||
chrTemp = "SUPER MARIO LEVEL SELECT";
|
||||
xPos = get_str_x_pos_from_center_custom_ascii(LUT_TYPE_STR_ASCII, SCREEN_WIDTH / 2, chrTemp, FALSE, 0);
|
||||
print_generic_string_ascii(xPos, 210, chrTemp);
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
|
||||
for (i = 0; i < MAX_PAGE_STRINGS; i++) {
|
||||
scene = (this->topDisplayedScene + i + this->count) % this->count;
|
||||
int_to_str(scene + 1, strScene);
|
||||
|
||||
if (scene == this->currentScene) {
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 126, 0, 255);
|
||||
} else {
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
}
|
||||
|
||||
name = gLevelSelectStageNames[scene];
|
||||
if (name == NULL) {
|
||||
name = "**Null**";
|
||||
}
|
||||
|
||||
print_generic_string(100, 190 - i * 12, strScene);
|
||||
print_generic_string_ascii(120, 190 - i * 12, name);
|
||||
}
|
||||
}
|
||||
|
||||
void print_debug_level_select_settings(void) {
|
||||
u8 strSaveNum[4];
|
||||
u8 strActNum[4];
|
||||
char *chrTemp;
|
||||
|
||||
s16 saveNum = gCurrSaveFileNum;
|
||||
s16 actNum = gCurrActNum;
|
||||
int_to_str(saveNum, strSaveNum);
|
||||
int_to_str(actNum, strActNum);
|
||||
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
|
||||
chrTemp = "Save File: ";
|
||||
print_generic_string_ascii(20, 40, chrTemp);
|
||||
print_generic_string(20 + get_string_width_ascii(chrTemp), 40, strSaveNum);
|
||||
chrTemp = "Level Act: ";
|
||||
print_generic_string_ascii(20, 20, chrTemp);
|
||||
print_generic_string(20 + get_string_width_ascii(chrTemp), 20, strActNum);
|
||||
}
|
||||
|
||||
void print_debug_level_select_strings(struct ZDebugLevelSelect *this) {
|
||||
|
||||
create_dl_ortho_matrix();
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||
|
||||
print_debug_level_select_menu(this);
|
||||
print_debug_level_select_settings();
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
}
|
||||
|
||||
Gfx *geo_debug_level_select_strings(s16 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx) {
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
print_debug_level_select_strings(gZDbgLevelSelect);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void debug_level_select_update(struct ZDebugLevelSelect *this) {
|
||||
if (this->verticalInputAccumulator == 0) {
|
||||
gCurrLevelNum = this->currentScene + 1;
|
||||
|
||||
if (gPlayer1Controller->buttonPressed & B_BUTTON) {
|
||||
gCurrActNum++;
|
||||
|
||||
if (gCurrActNum > 6) {
|
||||
gCurrActNum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonPressed & Z_TRIG) {
|
||||
gCurrSaveFileNum++;
|
||||
|
||||
if (gCurrSaveFileNum > 4) {
|
||||
gCurrSaveFileNum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonPressed & U_JPAD) {
|
||||
if (this->lockUp == TRUE) {
|
||||
this->timerUp = 0;
|
||||
}
|
||||
if (this->timerUp == 0) {
|
||||
this->timerUp = 20;
|
||||
this->lockUp = TRUE;
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
this->verticalInput = this->refreshRate;
|
||||
}
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonDown & U_JPAD && this->timerUp == 0) {
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
this->verticalInput = this->refreshRate * 3;
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonPressed & D_JPAD) {
|
||||
if (this->lockDown == TRUE) {
|
||||
this->timerDown = 0;
|
||||
}
|
||||
if (this->timerDown == 0) {
|
||||
this->timerDown = 20;
|
||||
this->lockDown = TRUE;
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
this->verticalInput = -this->refreshRate;
|
||||
}
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonDown & D_JPAD && this->timerDown == 0) {
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
this->verticalInput = -this->refreshRate * 3;
|
||||
}
|
||||
|
||||
if ((gPlayer1Controller->buttonPressed & L_JPAD) || (gPlayer1Controller->buttonDown & L_JPAD)) {
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
this->verticalInput = this->refreshRate;
|
||||
}
|
||||
|
||||
if ((gPlayer1Controller->buttonPressed & R_JPAD) || (gPlayer1Controller->buttonDown & R_JPAD)) {
|
||||
play_sound(SOUND_GENERAL_LEVEL_SELECT_CHANGE, gGlobalSoundSource);
|
||||
this->verticalInput = -this->refreshRate;
|
||||
}
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonPressed & R_TRIG) {
|
||||
this->pageDownIndex++;
|
||||
this->pageDownIndex =
|
||||
(this->pageDownIndex + ARRAY_COUNT(this->pageDownStops)) % ARRAY_COUNT(this->pageDownStops);
|
||||
this->currentScene = this->topDisplayedScene = this->pageDownStops[this->pageDownIndex];
|
||||
}
|
||||
|
||||
this->verticalInputAccumulator += this->verticalInput;
|
||||
|
||||
if (this->verticalInputAccumulator < -7) {
|
||||
this->verticalInput = 0;
|
||||
this->verticalInputAccumulator = 0;
|
||||
|
||||
this->currentScene++;
|
||||
this->currentScene = (this->currentScene + this->count) % this->count;
|
||||
|
||||
if (this->currentScene == ((this->topDisplayedScene + this->count + MAX_PAGE_STRINGS) % this->count)) {
|
||||
this->topDisplayedScene++;
|
||||
this->topDisplayedScene = (this->topDisplayedScene + this->count) % this->count;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->verticalInputAccumulator > 7) {
|
||||
this->verticalInput = 0;
|
||||
this->verticalInputAccumulator = 0;
|
||||
|
||||
if (this->currentScene == this->topDisplayedScene) {
|
||||
this->topDisplayedScene -= 2;
|
||||
this->topDisplayedScene = (this->topDisplayedScene + this->count) % this->count;
|
||||
}
|
||||
|
||||
this->currentScene--;
|
||||
this->currentScene = (this->currentScene + this->count) % this->count;
|
||||
|
||||
if (this->currentScene == ((this->topDisplayedScene + this->count) % this->count)) {
|
||||
this->topDisplayedScene--;
|
||||
this->topDisplayedScene = (this->topDisplayedScene + this->count) % this->count;
|
||||
}
|
||||
}
|
||||
|
||||
this->currentScene = (this->currentScene + this->count) % this->count;
|
||||
this->topDisplayedScene = (this->topDisplayedScene + this->count) % this->count;
|
||||
|
||||
if (this->timerUp != 0) {
|
||||
this->timerUp--;
|
||||
}
|
||||
|
||||
if (this->timerUp == 0) {
|
||||
this->lockUp = FALSE;
|
||||
}
|
||||
|
||||
if (this->timerDown != 0) {
|
||||
this->timerDown--;
|
||||
}
|
||||
|
||||
if (this->timerDown == 0) {
|
||||
this->lockDown = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
s32 lvl_init_intro_level_select(UNUSED s32 arg, UNUSED s32 unused) {
|
||||
s16 i;
|
||||
gCurrSaveFileNum = 1;
|
||||
gCurrActNum = 1;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(gZDbgLevelSelect->pageDownStops); i++) {
|
||||
gZDbgLevelSelect->pageDownStops[i] = MAX_PAGE_STRINGS * i;
|
||||
}
|
||||
|
||||
gZDbgLevelSelect->count = ARRAY_COUNT(gLevelSelectStageNames);
|
||||
gZDbgLevelSelect->verticalInputAccumulator = 0;
|
||||
gZDbgLevelSelect->verticalInput = 0;
|
||||
gZDbgLevelSelect->timerUp = 0;
|
||||
gZDbgLevelSelect->timerDown = 0;
|
||||
gZDbgLevelSelect->lockUp = 0;
|
||||
gZDbgLevelSelect->lockDown = 0;
|
||||
|
||||
gZDbgLevelSelect->currentScene = gCurrLevelNum - 1;
|
||||
gZDbgLevelSelect->topDisplayedScene = gCurrLevelNum - 1;
|
||||
|
||||
gZDbgLevelSelect->pageDownIndex = 0;
|
||||
|
||||
gZDbgLevelSelect->refreshRate = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s16 intro_level_select(void) {
|
||||
debug_level_select_update(gZDbgLevelSelect);
|
||||
|
||||
// Resets the game and disables level select
|
||||
if (gPlayer1Controller->buttonDown == (A_BUTTON | L_TRIG | R_TRIG)) {
|
||||
play_sound(SOUND_MENU_ENTER_HOLE, gGlobalSoundSource);
|
||||
gDebugLevelSelect = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Starts level selected
|
||||
if (gPlayer1Controller->buttonPressed & (A_BUTTON | START_BUTTON)) {
|
||||
play_sound(SOUND_MENU_STAR_SOUND, gGlobalSoundSource);
|
||||
return gCurrLevelNum;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
5
src/extras/redone/title_screen.inc.h
Normal file
5
src/extras/redone/title_screen.inc.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
Gfx *geo_debug_level_select_strings(s16 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx);
|
||||
|
||||
s32 lvl_init_intro_level_select(UNUSED s32 arg, UNUSED s32 unused);
|
|
@ -78,6 +78,9 @@ s32 run_level_id_or_demo(s32 level) {
|
|||
return level;
|
||||
}
|
||||
|
||||
#if ZELDA_STYLE_LEVEL_SELECT
|
||||
#include "extras/redone/title_screen.inc.c"
|
||||
#else
|
||||
/**
|
||||
* Level select intro function, updates the selected stage
|
||||
* count if an input was received. signals the stage to be started
|
||||
|
@ -143,6 +146,7 @@ s16 intro_level_select(void) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GODDARD_MFACE
|
||||
/**
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
#include <PR/ultratypes.h>
|
||||
|
||||
#include "macros.h"
|
||||
#include "config.h"
|
||||
|
||||
extern char gLevelSelectStageNames[][16];
|
||||
|
||||
extern char gLevelSelectStageNames[64][16];
|
||||
enum LevelScriptIntroArgs {
|
||||
LVL_INTRO_PLAY_ITS_A_ME_MARIO,
|
||||
LVL_INTRO_REGULAR,
|
||||
|
@ -13,6 +15,10 @@ enum LevelScriptIntroArgs {
|
|||
LVL_INTRO_LEVEL_SELECT
|
||||
};
|
||||
|
||||
#if ZELDA_STYLE_LEVEL_SELECT
|
||||
#include "extras/redone/title_screen.inc.h"
|
||||
#endif
|
||||
|
||||
s32 lvl_intro_update(s16 arg, UNUSED s32 unusedArg);
|
||||
|
||||
#endif // TITLE_SCREEN_H
|
||||
|
|
Loading…
Reference in a new issue