diff --git a/levels/menu/script.c b/levels/menu/script.c index 4e955c12..0673cdd4 100644 --- a/levels/menu/script.c +++ b/levels/menu/script.c @@ -18,6 +18,14 @@ #include "make_const_nonconst.h" #include "levels/menu/header.h" +static const LevelScript script_func_local_1[] = { + + /*0*/ CALL(/*arg*/ 0, /*func*/ resetLevelAct), + /*35*/ GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_ACT_NUM), + STOP_MUSIC(/*fadeOutTime*/ 0x00BE), + EXIT(), +}; + const LevelScript level_main_menu_entry_1[] = { INIT_LEVEL(), FIXED_LOAD(/*loadAddr*/ _goddardSegmentStart, /*romStart*/ _goddardSegmentRomStart, /*romEnd*/ _goddardSegmentRomEnd), @@ -59,7 +67,7 @@ const LevelScript level_main_menu_entry_1[] = { const LevelScript level_main_menu_entry_2[] = { /*0*/ CALL(/*arg*/ 0, /*func*/ lvl_set_current_level), - /*2*/ JUMP_IF(/*op*/ OP_EQ, /*arg*/ 0, level_main_menu_entry_2 + 42), + /*2*/ JUMP_LINK_IF(/*op*/ OP_EQ, /*arg*/ 0, script_func_local_1), /*5*/ INIT_LEVEL(), /*6*/ FIXED_LOAD(/*loadAddr*/ _goddardSegmentStart, /*romStart*/ _goddardSegmentRomStart, /*romEnd*/ _goddardSegmentRomEnd), /*10*/ LOAD_MIO0(/*seg*/ 0x07, _menu_segment_7SegmentRomStart, _menu_segment_7SegmentRomEnd), @@ -90,5 +98,5 @@ const LevelScript level_main_menu_entry_2[] = { /*40*/ CLEAR_LEVEL(), /*41*/ SLEEP_BEFORE_EXIT(/*frames*/ 1), // L1: - /*42*/ EXIT(), + /*42*/ EXIT(), }; diff --git a/src/game/hud.c b/src/game/hud.c index 1540b675..8f6feb4f 100644 --- a/src/game/hud.c +++ b/src/game/hud.c @@ -363,7 +363,43 @@ void render_hud_timer(void) { render_hud_tex_lut(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(46), 32, (*hudLUT)[GLYPH_DOUBLE_QUOTE]); gSPDisplayList(gDisplayListHead++, dl_hud_img_end); } +void render_hud_speedrunning_timer(void) { + u8 *(*hudLUT)[58]; + u16 timerValFrames; + u16 timerMins; + u16 timerSecs; + u16 timerFracSecs; + hudLUT = segmented_to_virtual(&main_hud_lut); + timerValFrames = gHudDisplay.speedRunTimer; +#ifdef VERSION_EU + switch (eu_get_language()) { + case LANGUAGE_ENGLISH: + print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(150), 185, "TIME"); + break; + case LANGUAGE_FRENCH: + print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(155), 185, "TEMPS"); + break; + case LANGUAGE_GERMAN: + print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(150), 185, "ZEIT"); + break; + } +#endif + timerMins = timerValFrames / (30 * 60); + timerSecs = (timerValFrames - (timerMins * 1800)) / 30; + + timerFracSecs = ((timerValFrames - (timerMins * 1800) - (timerSecs * 30)) & 0xFFFF) ; +#ifndef VERSION_EU + print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(190), 167, "RUN TIME"); +#endif + print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(91), 167, "%0d", timerMins); + print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(71), 167, "%02d", timerSecs); + print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(37), 167, "%02d", timerFracSecs); + gSPDisplayList(gDisplayListHead++, dl_hud_img_begin); + render_hud_tex_lut(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(81), 50, (*hudLUT)[GLYPH_APOSTROPHE]); + render_hud_tex_lut(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(46), 50, (*hudLUT)[GLYPH_DOUBLE_QUOTE]); + gSPDisplayList(gDisplayListHead++, dl_hud_img_end); +} /** * Sets HUD status camera value depending of the actions * defined in update_camera_status. @@ -476,6 +512,9 @@ void render_hud(void) { if (hudDisplayFlags & HUD_DISPLAY_FLAG_TIMER && configHUD) { render_hud_timer(); + } + if (hudDisplayFlags & HUD_DISPLAY_FLAG_SPEED_TIMER && configHUD) { + render_hud_speedrunning_timer(); } } } diff --git a/src/game/level_update.c b/src/game/level_update.c index 72a6a607..fef25d37 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -162,6 +162,7 @@ u16 D_80339ECA; s16 sTransitionTimer; void (*sTransitionUpdate)(s16 *); struct WarpDest sWarpDest; +struct WarpDest storedWarpDest; s16 D_80339EE0; s16 sDelayedWarpOp; s16 sDelayedWarpTimer; @@ -171,6 +172,7 @@ s32 sDelayedWarpArg; s16 unusedEULevelUpdateBss1; #endif s8 sTimerRunning; +s8 speedTimerRunning; s8 gShouldNotPlayCastleMusic; struct MarioState *gMarioState = &gMarioStates[0]; @@ -179,6 +181,7 @@ s8 D_8032C9E0 = 0; u8 unused3[4]; u8 unused4[2]; + u16 level_control_timer(s32 timerOp) { switch (timerOp) { case TIMER_CONTROL_SHOW: @@ -204,6 +207,31 @@ u16 level_control_timer(s32 timerOp) { return gHudDisplay.timer; } +u16 speed_running_control_timer(s32 timerOp) { + switch (timerOp) { + case TIMER_CONTROL_SHOW: + gHudDisplay.flags |= HUD_DISPLAY_FLAG_SPEED_TIMER; + speedTimerRunning = FALSE; + gHudDisplay.speedRunTimer = 0; + break; + + case TIMER_CONTROL_START: + speedTimerRunning = TRUE; + break; + + case TIMER_CONTROL_STOP: + speedTimerRunning = FALSE; + break; + + case TIMER_CONTROL_HIDE: + gHudDisplay.flags &= ~HUD_DISPLAY_FLAG_SPEED_TIMER; + speedTimerRunning = FALSE; + gHudDisplay.speedRunTimer = 0; + break; + } + + return gHudDisplay.speedRunTimer; +} u32 pressed_pause(void) { u32 val4 = get_dialog_id() >= 0; @@ -478,9 +506,12 @@ void warp_level(void) { gCurrLevelNum = sWarpDest.levelNum; level_control_timer(TIMER_CONTROL_HIDE); + load_area(sWarpDest.areaIdx); init_mario_after_warp(); + speed_running_control_timer(TIMER_CONTROL_SHOW); + speed_running_control_timer(TIMER_CONTROL_START); } void warp_credits(void) { @@ -670,6 +701,7 @@ void initiate_painting_warp(void) { if (!(warpNode.destLevel & 0x80)) { D_8032C9E0 = check_warp_checkpoint(&warpNode); } + skipStarSelect = false; initiate_warp(warpNode.destLevel & 0x7F, warpNode.destArea, warpNode.destNode, 0); check_if_should_set_warp_checkpoint(&warpNode); @@ -979,7 +1011,9 @@ s32 play_mode_normal(void) { if (sTimerRunning && gHudDisplay.timer < 17999) { gHudDisplay.timer += 1; } - + if (speedTimerRunning) { + gHudDisplay.speedRunTimer += 1; + } area_update_objects(); update_hud_values(); @@ -1224,7 +1258,7 @@ s32 init_level(void) { if (gMarioState->action == ACT_INTRO_CUTSCENE) { sound_banks_disable(2, 0x0330); } - + return 1; } @@ -1315,9 +1349,16 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { return 0; } + if(skipStarSelect){ + return 0; + } + return 1; } +s32 resetLevelAct(UNUSED s16 arg0) { + return levelResetActNum; +} /** * Play the "thank you so much for to playing my game" sound. */ diff --git a/src/game/level_update.h b/src/game/level_update.h index ecf9c3a3..6e707112 100644 --- a/src/game/level_update.h +++ b/src/game/level_update.h @@ -78,7 +78,7 @@ struct WarpDest { u8 nodeId; u32 arg; }; - +extern struct WarpDest storedWarpDest; extern struct WarpDest sWarpDest; extern s16 D_80339EE0; @@ -97,6 +97,7 @@ struct HudDisplay { /*0x08*/ s16 keys; /*0x0A*/ s16 flags; /*0x0C*/ u16 timer; + u32 speedRunTimer; }; extern struct HudDisplay gHudDisplay; @@ -110,6 +111,7 @@ enum HUDDisplayFlag { HUD_DISPLAY_FLAG_KEYS = 0x0010, HUD_DISPLAY_FLAG_UNKNOWN_0020 = 0x0020, HUD_DISPLAY_FLAG_TIMER = 0x0040, + HUD_DISPLAY_FLAG_SPEED_TIMER = 0x0080, HUD_DISPLAY_FLAG_EMPHASIZE_POWER = 0x8000, HUD_DISPLAY_NONE = 0x0000, @@ -126,6 +128,7 @@ void level_set_transition(s16 length, void (*updateFunction)(s16 *)); s32 lvl_init_or_update(s16 initOrUpdate, UNUSED s32 unused); s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum); s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum); +s32 resetLevelAct(UNUSED s16 arg0); s32 lvl_play_the_end_screen_sound(UNUSED s16 arg0, UNUSED s32 arg1); void basic_update(UNUSED s16 *arg); diff --git a/src/game/mario.c b/src/game/mario.c index 5f8e5114..cd645541 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -37,7 +37,11 @@ #include "pc/cheats.h" #ifdef BETTERCAMERA #include "bettercamera.h" +extern f32 newcam_yaw_acc; +extern f32 newcam_tilt_acc; #endif +int levelResetActNum = 0; +u8 skipStarSelect = false; u32 unused80339F10; s8 filler80339F1C[20]; @@ -1413,7 +1417,32 @@ void update_mario_inputs(struct MarioState *m) { update_mario_geometry_inputs(m); debug_print_speed_action_normal(m); - + + if (m->controller->buttonDown & L_TRIG && m->controller->buttonPressed & R_TRIG) { + storedWarpDest = sWarpDest; + levelResetActNum = gCurrActNum; + } + if (m->controller->buttonDown & Z_TRIG && m->controller->buttonPressed & R_TRIG) { + skipStarSelect = true; + + m->health = 0x880; + if (storedWarpDest.levelNum != 0) { + sWarpDest = storedWarpDest; + levelResetActNum = gCurrActNum; + + } else { + sWarpDest.levelNum = gCurrLevelNum; + sWarpDest.areaIdx = m->area->index; + levelResetActNum = gCurrActNum; + } + + sWarpDest.type = 1; + reset_dialog_render_state(); +#ifdef BETTERCAMERA + newcam_yaw_acc = 0; + newcam_tilt_acc = 0; +#endif + } /* Moonjump cheat */ while (Cheats.MoonJump == true && Cheats.EnableCheats == true && m->controller->buttonDown & L_TRIG ){ m->vel[1] = 25; diff --git a/src/game/mario.h b/src/game/mario.h index ad0d005a..004b8f7d 100644 --- a/src/game/mario.h +++ b/src/game/mario.h @@ -50,5 +50,7 @@ s32 set_water_plunge_action(struct MarioState *m); s32 execute_mario_action(UNUSED struct Object *o); void init_mario(void); void init_mario_from_save_file(void); + extern s32 levelResetActNum; + extern u8 skipStarSelect; #endif // MARIO_H diff --git a/src/menu/star_select.c b/src/menu/star_select.c index 08b988e6..27f41d30 100644 --- a/src/menu/star_select.c +++ b/src/menu/star_select.c @@ -52,6 +52,7 @@ static s8 sSelectableStarIndex = 0; // Act Selector menu timer that keeps counting until you choose an act. static s32 sActSelectorMenuTimer = 0; + /** * Act Selector Star Type Loop Action * Defines a select type for a star in the act selector. @@ -397,12 +398,12 @@ s32 lvl_init_act_selector_values_and_stars(UNUSED s32 arg, UNUSED s32 unused) { sSelectedActIndex = 0; sSelectableStarIndex = 0; sObtainedStars = save_file_get_course_star_count(gCurrSaveFileNum - 1, gCurrCourseNum - 1); - + // Don't count 100 coin star if (stars & (1 << 6)) { sObtainedStars--; } - + //! no return value #ifdef AVOID_UB return 0;