diff --git a/src/game/game_init.c b/src/game/game_init.c index af5fe146..f9d79dde 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -19,6 +19,7 @@ #include "segment2.h" #include "segment_symbols.h" #include "rumble_init.h" +#include "port/ui/cvar_prefixes.h" #include "port/interpolation/FrameInterpolation.h" // First 3 controller slots @@ -503,28 +504,29 @@ void run_demo_inputs(void) { gControllers[0].controllerData->stick_x = 0; gControllers[0].controllerData->stick_y = 0; gControllers[0].controllerData->button = END_DEMO; - gCurrDemoInput = NULL; } 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; - // 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; + if(CVarGetInteger(CVAR_CHEAT("PlayInDemo"), 0) == 0) { + // 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; - // 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 - // A, B, Z, Start, and the C-Buttons are used in a demo, as bits - // in that order. In order to assign the mask, we need to take the - // 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 = - ((gCurrDemoInput->buttonMask & 0xF0) << 8) + ((gCurrDemoInput->buttonMask & 0xF)); + // 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 + // A, B, Z, Start, and the C-Buttons are used in a demo, as bits + // in that order. In order to assign the mask, we need to take the + // 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 = + ((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; + // If start was pushed, put it into the demo sequence being input to end the demo. + gControllers[0].controllerData->button |= startPushed; + } // Run the current demo input's timer down. if it hits 0, advance the demo input list. if (--gCurrDemoInput->timer == 0) { diff --git a/src/game/level_update.c b/src/game/level_update.c index 125bbec9..b474e1d0 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -29,6 +29,7 @@ #include "course_table.h" #include "rumble_init.h" +#include "port/ui/cvar_prefixes.h" #include "port/hooks/list/EngineEvent.h" #include "port/mods/PortEnhancements.h" @@ -957,7 +958,7 @@ void basic_update(UNUSED s16 *arg) { } s32 play_mode_normal(void) { - if (gCurrDemoInput != NULL) { + if (gCurrDemoInput != NULL && CVarGetInteger(CVAR_CHEAT("PlayInDemo"), 0) == 0) { print_intro_text(); if (gPlayer1Controller->buttonPressed & END_DEMO) { level_trigger_warp(gMarioState, diff --git a/src/menu/title_screen.c b/src/menu/title_screen.c index e08bd1dd..fba8bfbc 100644 --- a/src/menu/title_screen.c +++ b/src/menu/title_screen.c @@ -53,23 +53,22 @@ static const char* gDemoInputs[8] = { s32 run_level_id_or_demo(s32 level) { gCurrDemoInput = NULL; - if (level == LEVEL_NONE) { + if (level == LEVEL_NONE && !gDebugLevelSelect) { if (!gPlayer1Controller->buttonDown && !gPlayer1Controller->stickMag) { // start the demo. 800 frames has passed while // player is idle on PRESS START screen. if ((++sDemoCountdown) == PRESS_START_DEMO_TIMER) { + // if the next demo sequence ID is the count limit, reset it back to + // the first sequence. + if (gDemoInputListID >= ARRAY_COUNT(gDemoInputs) - 1) { + gDemoInputListID = 0; + } // start the Mario demo animation for the demo list. void* data = segmented_to_virtual(gDemoInputs[gDemoInputListID]); if(data == NULL) { - return 0; - } - - // if the next demo sequence ID is the count limit, reset it back to - // the first sequence. - if (++gDemoInputListID == ARRAY_COUNT(gDemoInputs)) { - gDemoInputListID = 0; + return level; } // add 1 (+4) to the pointer to skip the first 4 bytes @@ -79,6 +78,7 @@ s32 run_level_id_or_demo(s32 level) { level = (s8)((struct DemoInput *) data)->timer; gCurrSaveFileNum = 1; gCurrActNum = 1; + gDemoInputListID++; } } else { // activity was detected, so reset the demo countdown. sDemoCountdown = 0; diff --git a/src/port/ui/GhostshipMenuEnhancements.cpp b/src/port/ui/GhostshipMenuEnhancements.cpp index 4762f640..8a00915b 100644 --- a/src/port/ui/GhostshipMenuEnhancements.cpp +++ b/src/port/ui/GhostshipMenuEnhancements.cpp @@ -163,6 +163,10 @@ void GhostshipMenu::AddMenuEnhancements() { .CVar(CVAR_CHEAT("PauseExitWhenever")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Exit from anywhere using the Pause Menu.")); + AddWidget(path, "Play In Demo", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_CHEAT("PlayInDemo")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip("Allows normal gameplay when a demo is playing.")); } } // namespace GhostshipGui