Path: blob/master/SonicMania/Objects/Menu/MenuSetup.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: MenuSetup Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectMenuSetup *MenuSetup;1011void MenuSetup_Update(void)12{13RSDK_THIS(MenuSetup);1415StateMachine_Run(self->state);1617#if !MANIA_USE_PLUS18if (self->state != MenuSetup_State_SetupLeaderboards) {19#endif2021if (self->timer >= self->delay) {22StateMachine_Run(self->callback);23destroyEntity(self);24}25else {26self->timer++;27}2829#if !MANIA_USE_PLUS30}31#endif32}3334void MenuSetup_LateUpdate(void) {}3536void MenuSetup_StaticUpdate(void)37{38#if MANIA_USE_PLUS39if (!MenuSetup->initializedAPI) {40MenuSetup->fxFade->speedOut = 0;4142String tag;43INIT_STRING(tag);44RSDK.SetString(&tag, "Main Menu");4546EntityUIControl *mainMenu = NULL; // this will crash if no entities have "Main Menu" as the tag, make sure one does!!!47foreach_all(UIControl, control)48{49if (RSDK.CompareStrings(&tag, &control->tag, false)) {50mainMenu = control;51foreach_break;52}53}5455if (!ManiaModeMenu_InitAPI()) {56mainMenu->selectionDisabled = true;57return;58}59else {60mainMenu->selectionDisabled = false;61MenuSetup->initializedAPI = true;6263String message;64Localization_GetString(&message, STR_RPC_MENU);65API_SetRichPresence(PRESENCE_MENU, &message);66}67}6869if (!MenuSetup->initializedMenu) {70ManiaModeMenu_Initialize();71MenuSetup->initializedMenu = true;72}7374if (!MenuSetup->initializedMenuReturn) {75ManiaModeMenu_HandleMenuReturn();76MenuSetup->initializedMenuReturn = true;77ManiaModeMenu_SetBGColors();7879if (!globals->suppressAutoMusic)80ManiaModeMenu_ChangeMenuTrack();8182globals->suppressAutoMusic = false;83}8485MenuSetup->fxFade->speedOut = 12;86DialogRunner_GetUserAuthStatus();87#else88if (!MenuSetup->initializedAPI) {89String tag;90INIT_STRING(tag);91RSDK.SetString(&tag, "Main Menu");9293EntityUIControl *mainMenu = NULL; // this will crash if no entities have "Main Menu" as the tag, make sure one does!!!94foreach_all(UIControl, control)95{96if (RSDK.CompareStrings(&tag, &control->tag, false)) {97mainMenu = control;98foreach_break;99}100}101102if (!MenuSetup_InitAPI()) {103mainMenu->selectionDisabled = true;104return;105}106else {107mainMenu->selectionDisabled = false;108MenuSetup->initializedAPI = true;109110String message;111Localization_GetString(&message, STR_RPC_MENU);112API_SetRichPresence(PRESENCE_MENU, &message);113}114}115116if (!MenuSetup->initializedMenu) {117MenuSetup_Initialize();118MenuSetup->initializedMenu = true;119}120121if (!MenuSetup->initializedMenuReturn) {122MenuSetup_HandleMenuReturn();123MenuSetup->initializedMenuReturn = true;124MenuSetup_SetBGColors();125126if (!globals->suppressAutoMusic)127MenuSetup_ChangeMenuTrack();128129globals->suppressAutoMusic = false;130}131132APICallback_GetUserAuthStatus();133#endif134}135136void MenuSetup_Draw(void)137{138RSDK_THIS(MenuSetup);139140RSDK.FillScreen(self->fadeColor, self->fadeTimer, self->fadeTimer - 128, self->fadeTimer - 256);141}142143void MenuSetup_Create(void *data)144{145RSDK_THIS(MenuSetup);146147self->active = ACTIVE_ALWAYS;148self->visible = true;149self->drawGroup = 14;150}151152void MenuSetup_StageLoad(void)153{154#if MANIA_USE_PLUS155EntityMenuParam *param = MenuParam_GetParam();156LogHelpers_Print("Menu recall ctrl: %s", param->menuTag);157158MenuSetup->initializedMenuReturn = false;159MenuSetup->initializedMenu = false;160MenuSetup->initializedAPI = false;161MenuSetup->initializedSaves = false;162MenuSetup->fxFade = NULL;163164if (!globals->suppressAutoMusic) {165Music_Stop();166Music->activeTrack = TRACK_NONE;167}168#else169Music_Stop();170Music->activeTrack = TRACK_NONE;171#endif172173if (!SceneInfo->inEditor) {174switch (sku_platform) {175case PLATFORM_PC: LogHelpers_Print("PC SKU"); break;176case PLATFORM_PS4: LogHelpers_Print("PS4 SKU"); break;177case PLATFORM_XB1: LogHelpers_Print("XB1 SKU"); break;178case PLATFORM_SWITCH: LogHelpers_Print("NX SKU"); break;179case PLATFORM_DEV: LogHelpers_Print("DEV SKU"); break;180default: LogHelpers_Print("INVALID PLATFORM: %d", sku_platform); break;181}182183switch (sku_region) {184case REGION_US: LogHelpers_Print("US REGION"); break;185case REGION_JP: LogHelpers_Print("JP REGION"); break;186case REGION_EU: LogHelpers_Print("EU REGION"); break;187default: LogHelpers_Print("INVALID REGION: %d", sku_region); break;188}189}190191// Bug Details(?):192// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)193// but the memset size is only 1024 (sizeof(uint8) * 0x400)194// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal195memset(globals->noSaveSlot, 0, 0x400);196197globals->continues = 0;198#if MANIA_USE_PLUS199globals->recallEntities = false;200#else201MenuSetup->vsTotalTimer = 120;202#endif203204RSDK.SetVideoSetting(VIDEOSETTING_SCREENCOUNT, 1);205206foreach_all(FXFade, fade) { MenuSetup->fxFade = fade; }207}208209void MenuSetup_StartTransition(void (*callback)(void), int32 delay)210{211EntityMenuSetup *menuSetup = CREATE_ENTITY(MenuSetup, NULL, -0x100000, -0x100000);212213menuSetup->active = ACTIVE_ALWAYS;214menuSetup->fadeColor = 0x000000;215menuSetup->fadeShift = 5;216menuSetup->delay = delay;217#if MANIA_USE_PLUS218menuSetup->state = ManiaModeMenu_State_HandleTransition;219#else220menuSetup->state = MenuSetup_State_HandleTransition;221#endif222menuSetup->callback = callback;223}224225#if !MANIA_USE_PLUS226void MenuSetup_StartTransitionLB(void (*callback)(void), int32 delay)227{228EntityMenuSetup *menuSetup = CREATE_ENTITY(MenuSetup, NULL, -0x100000, -0x100000);229230menuSetup->active = ACTIVE_ALWAYS;231menuSetup->fadeColor = 0x000000;232menuSetup->fadeShift = 5;233menuSetup->delay = delay;234menuSetup->state = MenuSetup_State_SetupLeaderboards;235menuSetup->callback = callback;236}237#endif238239// START PRE-PLUS AREA240#if !MANIA_USE_PLUS241void MenuSetup_Initialize(void)242{243String tag;244INIT_STRING(tag);245246foreach_all(UIControl, control)247{248RSDK.SetString(&tag, "Main Menu");249if (RSDK.CompareStrings(&tag, &control->tag, false)) {250MenuSetup->mainMenu = control;251control->backPressCB = MenuSetup_BackPressCB_ReturnToTitle;252}253254RSDK.SetString(&tag, "Time Attack");255if (RSDK.CompareStrings(&tag, &control->tag, false))256MenuSetup->timeAttack = control;257258RSDK.SetString(&tag, "Time Attack Zones");259if (RSDK.CompareStrings(&tag, &control->tag, false))260MenuSetup->timeAttackZones = control;261262RSDK.SetString(&tag, "Leaderboards");263if (RSDK.CompareStrings(&tag, &control->tag, false)) {264MenuSetup->leaderboards = control;265control->backPressCB = MenuSetup_TA_Leaderboards_BackPressCB;266}267268RSDK.SetString(&tag, "Competition");269if (RSDK.CompareStrings(&tag, &control->tag, false)) {270MenuSetup->competition = control;271control->backPressCB = MenuSetup_VS_BackoutFromVsCharSelect;272}273274RSDK.SetString(&tag, "Competition Rules");275if (RSDK.CompareStrings(&tag, &control->tag, false))276MenuSetup->competitionRules = control;277278RSDK.SetString(&tag, "Competition Zones");279if (RSDK.CompareStrings(&tag, &control->tag, false)) {280MenuSetup->competitionZones = control;281control->backPressCB = MenuSetup_VS_CompZones_BackPressCB;282}283284RSDK.SetString(&tag, "Competition Round");285if (RSDK.CompareStrings(&tag, &control->tag, false))286MenuSetup->competitionRound = control;287288RSDK.SetString(&tag, "Competition Total");289if (RSDK.CompareStrings(&tag, &control->tag, false))290MenuSetup->competitionTotal = control;291292RSDK.SetString(&tag, "Save Select");293if (RSDK.CompareStrings(&tag, &control->tag, false))294MenuSetup->saveSelect = control;295296RSDK.SetString(&tag, "No Save Mode");297if (RSDK.CompareStrings(&tag, &control->tag, false))298MenuSetup->noSaveMode = control;299300RSDK.SetString(&tag, "Secrets");301if (RSDK.CompareStrings(&tag, &control->tag, false))302MenuSetup->secrets = control;303304RSDK.SetString(&tag, "Extras");305if (RSDK.CompareStrings(&tag, &control->tag, false))306MenuSetup->extras = control;307308RSDK.SetString(&tag, "Options");309if (RSDK.CompareStrings(&tag, &control->tag, false))310MenuSetup->options = control;311312RSDK.SetString(&tag, "Language");313if (RSDK.CompareStrings(&tag, &control->tag, false))314MenuSetup->language = control;315316RSDK.SetString(&tag, "Video");317if (RSDK.CompareStrings(&tag, &control->tag, false))318MenuSetup->video = control;319320RSDK.SetString(&tag, "Video WIN");321if (RSDK.CompareStrings(&tag, &control->tag, false))322MenuSetup->video_win = control;323324RSDK.SetString(&tag, "Sound");325if (RSDK.CompareStrings(&tag, &control->tag, false))326MenuSetup->sound = control;327328RSDK.SetString(&tag, "Controls WIN");329if (RSDK.CompareStrings(&tag, &control->tag, false))330MenuSetup->controls_win = control;331332RSDK.SetString(&tag, "Controls KB");333if (RSDK.CompareStrings(&tag, &control->tag, false))334MenuSetup->controls_KB = control;335336RSDK.SetString(&tag, "Controls PS4");337if (RSDK.CompareStrings(&tag, &control->tag, false))338MenuSetup->controls_PS4 = control;339340RSDK.SetString(&tag, "Controls XB1");341if (RSDK.CompareStrings(&tag, &control->tag, false))342MenuSetup->controls_XB1 = control;343344RSDK.SetString(&tag, "Controls NX");345if (RSDK.CompareStrings(&tag, &control->tag, false))346MenuSetup->controls_NX = control;347348RSDK.SetString(&tag, "Controls NX Grip");349if (RSDK.CompareStrings(&tag, &control->tag, false))350MenuSetup->controls_NX_Grip = control;351352RSDK.SetString(&tag, "Controls NX Joycon");353if (RSDK.CompareStrings(&tag, &control->tag, false))354MenuSetup->controls_NX_JoyCon = control;355356RSDK.SetString(&tag, "Controls NX Pro");357if (RSDK.CompareStrings(&tag, &control->tag, false))358MenuSetup->controls_NX_Pro = control;359}360361foreach_all(UIButtonPrompt, prompt)362{363EntityUIControl *saveControl = MenuSetup->saveSelect;364EntityUIControl *leaderboardsControl = MenuSetup->leaderboards;365EntityUIControl *optionsControl = MenuSetup->options;366367if (UIControl_ContainsPos(saveControl, &prompt->position) && prompt->buttonID == 2)368MenuSetup->delSavePrompt = prompt;369370if (UIControl_ContainsPos(leaderboardsControl, &prompt->position) && prompt->buttonID == 3)371MenuSetup->leaderboardPrompt = prompt;372373if (UIControl_ContainsPos(optionsControl, &prompt->position) && prompt->buttonID == 3)374MenuSetup->optionsPrompt = prompt;375}376377foreach_all(UILeaderboard, leaderboard) { MenuSetup->leaderboardWidget = leaderboard; }378379foreach_all(UIInfoLabel, label)380{381EntityUIControl *roundControl = MenuSetup->competitionRound;382EntityUIControl *totalControl = MenuSetup->competitionTotal;383384if (UIControl_ContainsPos(roundControl, &label->position))385MenuSetup->roundLabel = label;386387if (UIControl_ContainsPos(totalControl, &label->position))388MenuSetup->totalLabel = label;389}390391foreach_all(UIVsScoreboard, scoreboard)392{393EntityUIControl *roundControl = MenuSetup->competitionRound;394EntityUIControl *totalControl = MenuSetup->competitionTotal;395396if (UIControl_ContainsPos(roundControl, &scoreboard->position)) {397MenuSetup->roundScoreboard = scoreboard;398scoreboard->parentPos = &roundControl->position;399}400401if (UIControl_ContainsPos(totalControl, &scoreboard->position)) {402MenuSetup->totalScoreboard = scoreboard;403scoreboard->parentPos = &totalControl->position;404}405}406407MenuSetup_HandleUnlocks();408MenuSetup_SetupActions();409}410411bool32 MenuSetup_InitAPI(void)412{413if (!MenuSetup->initializedAPI)414MenuSetup->fxFade->timer = 512;415416APICallback_GetUserAuthStatus();417418if (!APICallback->authStatus) {419APICallback_TryAuth();420}421else if (APICallback->authStatus != STATUS_CONTINUE) {422int32 storageStatus = APICallback_GetStorageStatus();423424if (!storageStatus) {425APICallback_TryInitStorage();426}427else if (storageStatus != STATUS_CONTINUE) {428if (!API_GetNoSave() && (APICallback->authStatus != STATUS_OK || storageStatus != STATUS_OK)) {429if (APICallback->saveStatus != STATUS_CONTINUE) {430if (APICallback->saveStatus != STATUS_FORBIDDEN) {431APICallback_PromptSavePreference(storageStatus);432}433else {434RSDK.SetScene("Presentation", "Title Screen");435RSDK.LoadScene();436}437}438439return false;440}441442if (!MenuSetup->initializedSaves) {443UIWaitSpinner_StartWait();444Options_LoadFile(Options_LoadCallback);445SaveGame_LoadFile(SaveGame_SaveLoadedCB);446447MenuSetup->initializedSaves = true;448}449450if (MenuSetup->initializedAPI)451return true;452453if (globals->optionsLoaded == STATUS_OK && globals->saveLoaded == STATUS_OK) {454455if (!API_GetNoSave() && APICallback_NotifyAutosave())456return false;457458UIWaitSpinner_FinishWait();459if (APICallback_CheckUnreadNotifs())460return false;461462MenuSetup->initializedAPI = true;463return true;464}465466if (API_GetNoSave()) {467UIWaitSpinner_FinishWait();468469return true;470}471else {472if (globals->optionsLoaded == STATUS_ERROR || globals->saveLoaded == STATUS_ERROR) {473if (APICallback->saveStatus != STATUS_CONTINUE) {474if (APICallback->saveStatus == STATUS_FORBIDDEN) {475RSDK.SetScene("Presentation", "Title Screen");476RSDK.LoadScene();477}478else {479APICallback_PromptSavePreference(STATUS_CORRUPT);480}481}482}483}484}485}486487return false;488}489490void MenuSetup_SetupActions(void)491{492EntityUIControl *comp = MenuSetup->competition;493EntityUIControl *options = MenuSetup->options;494EntityUIControl *video = MenuSetup->video;495EntityUIControl *video_win = MenuSetup->video_win;496EntityUIControl *controls_win = MenuSetup->controls_win;497EntityUIControl *sound = MenuSetup->sound;498EntityUIControl *saveSel = MenuSetup->saveSelect;499EntityUIControl *secrets = MenuSetup->secrets;500EntityUIControl *extras = MenuSetup->extras;501EntityUIControl *compTotal = MenuSetup->competitionTotal;502EntityUIControl *compRound = MenuSetup->competitionRound;503EntityUIControl *compRules = MenuSetup->competitionRules;504EntityUIControl *language = MenuSetup->language;505506foreach_all(UIModeButton, modeButton) { modeButton->actionCB = MenuSetup_MenuButton_ActionCB; }507foreach_all(UISaveSlot, saveSlot) { saveSlot->actionCB = MenuSetup_SaveSlot_ActionCB; }508509foreach_all(UIButton, button)510{511switch (button->listID) {512case 17:513if (!button->frameID) {514if (GameInfo->platform == PLATFORM_PC || GameInfo->platform == PLATFORM_DEV) {515button->actionCB = MenuSetup_ExitGame_ActionCB;516}517else {518EntityUIControl *control = MenuSetup->mainMenu;519--control->buttonCount;520control->buttons[5] = NULL;521destroyEntity(button);522}523}524break;525526case 1:527if (button->frameID == 4)528button->actionCB = MenuSetup_OpenExtrasMenu_ActionCB;529break;530531case 7:532if (button->frameID == 4) {533button->actionCB = MenuSetup_Extras_DAGarden_ActionCB;534}535else if (button->frameID == 8) {536button->actionCB = MenuSetup_Extras_Credits_ActionCB;537button->clearParentState = true;538}539break;540}541542if (UIControl_ContainsPos(controls_win, &button->position))543button->actionCB = MenuSetup_Options_OpenKBControlsMenu;544545if (UIControl_ContainsPos(compRules, &button->position) && button->listID == 9 && button->frameID == 2)546button->actionCB = MenuSetup_VS_RulesButton_ActionCB;547548if (UIControl_ContainsPos(secrets, &button->position) && button->listID == 9 && button->frameID == 2)549button->actionCB = MenuSetup_OpenSaveSelectMenu;550551if (UIControl_ContainsPos(options, &button->position) && button->listID == 3) {552switch (button->frameID) {553case 0: button->actionCB = MenuSetup_Options_VideoMenuButton_ActionCB; break;554case 1: button->actionCB = MenuSetup_Options_SoundMenuButton_ActionCB; break;555case 2: button->actionCB = MenuSetup_Options_ControlsMenuButton_ActionCB; break;556case 3: button->actionCB = MenuSetup_Options_LanguageMenuButton_ActionCB; break;557}558}559560if (UIControl_ContainsPos(language, &button->position))561button->actionCB = MenuSetup_OptionsLanguage_LanguageButton_ActionCB;562563if (UIControl_ContainsPos(video, &button->position) && button->listID == 3 && button->frameID == 0)564button->choiceChangeCB = MenuSetup_OptionsVideo_ShaderButton_ActionCB;565566if (UIControl_ContainsPos(video_win, &button->position) && button->listID == 17) {567switch (button->frameID) {568case 2: button->choiceChangeCB = MenuSetup_OptionsVideo_ShaderButton_ActionCB; break;569case 7: button->choiceChangeCB = MenuSetup_OptionsVideo_WindowScaleButton_ActionCB; break;570case 13: button->choiceChangeCB = MenuSetup_OptionsVideo_BorderlessButton_ActionCB; break;571case 14: button->choiceChangeCB = MenuSetup_OptionsVideo_FullscreenButton_ActionCB; break;572case 15: button->choiceChangeCB = MenuSetup_OptionsVideo_VSyncButton_ActionCB; break;573case 16: button->choiceChangeCB = MenuSetup_OptionsVideo_TripleBufferButton_ActionCB; break;574default: break;575}576}577}578579foreach_all(UIChoice, choice)580{581if (choice->listID == 7) {582switch (choice->frameID) {583case 2:584choice->actionCB = MenuSetup_Extras_Puyo_vsAI_ActionCB;585choice->textVisible = true;586break;587588case 3:589choice->actionCB = MenuSetup_Extras_Puyo_vs2P_ActionCB;590choice->textVisible = true;591break;592593case 6:594choice->actionCB = MenuSetup_Extras_BSS_3K_ActionCB;595choice->textVisible = true;596break;597598case 7:599choice->actionCB = MenuSetup_Extras_BSS_Mania_ActionCB;600choice->textVisible = true;601break;602603default: break;604}605}606}607608foreach_all(UICharButton, charButton)609{610if (charButton->parent == (Entity *)MenuSetup->timeAttack) {611switch (charButton->characterID) {612case 0: charButton->actionCB = MenuSetup_TA_OpenZoneList_Sonic; break;613case 1: charButton->actionCB = MenuSetup_TA_OpenZoneList_Tails; break;614case 2: charButton->actionCB = MenuSetup_TA_OpenZoneList_Knux; break;615}616}617}618619foreach_all(UITAZoneModule, module) { module->actionCB = MenuSetup_TA_TAZoneModule_ActionCB; }620621MenuSetup->leaderboardWidget->yPressCB = MenuSetup_TA_Leaderboards_YPressCB;622623foreach_all(UISlider, slider)624{625if (UIControl_ContainsPos(sound, &slider->position) && slider->listID == 5)626slider->sliderChangedCB = MenuSetup_OptionsVideo_UISlider_ChangedCB;627}628629comp->processButtonInputCB = MenuSetup_VS_ProcessButtonCB;630comp->menuSetupCB = MenuSetup_VS_MenuSetupCB;631632if (comp->active == ACTIVE_ALWAYS) {633RSDK_THIS(UIControl);634self->childHasFocus = false;635636foreach_all(UIVsCharSelector, selector)637{638selector->isSelected = true;639selector->ready = false;640selector->processButtonCB = UIVsCharSelector_ProcessButtonCB;641}642}643644compRound->processButtonInputCB = MenuSetup_VS_Round_ProcessButtonCB;645compRound->menuSetupCB = MenuSetup_VS_Round_MenuSetupCB;646if (compRound->active == ACTIVE_ALWAYS)647MenuSetup_VS_Round_MenuSetupCB();648649compTotal->processButtonInputCB = MenuSetup_VS_Total_ProcessButtonCB;650compTotal->menuSetupCB = MenuSetup_VS_Total_MenuSetupCB;651compTotal->menuUpdateCB = MenuSetup_VS_Total_MenuUpdateCB;652compTotal->targetPos.y = compTotal->startPos.y;653compTotal->position.y = compTotal->startPos.y;654if (compTotal->active == ACTIVE_ALWAYS)655MenuSetup_VS_Total_MenuSetupCB();656657saveSel->menuUpdateCB = MenuSetup_SaveSel_MenuUpdateCB;658saveSel->yPressCB = MenuSetup_SaveSel_YPressCB;659660extras->processButtonInputCB = MenuSetup_Extras_ProcessButtonCB;661662options->menuSetupCB = MenuSetup_Options_MenuSetupCB;663if (sku_platform == PLATFORM_DEV || sku_platform == PLATFORM_SWITCH)664options->yPressCB = MenuSetup_Options_LaunchManual;665else666MenuSetup->optionsPrompt->visible = false;667668video_win->menuUpdateCB = MenuSetup_OptionsVideo_Win_MenuUpdateCB;669670foreach_all(UIVsZoneButton, zoneButton) { zoneButton->actionCB = MenuSetup_VS_StartMatch_ActionCB; }671}672673void MenuSetup_HandleUnlocks(void)674{675EntityUIControl *mainMenu = MenuSetup->mainMenu;676677EntityUIButton *taButton = mainMenu->buttons[1];678taButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_TIMEATTACK);679680EntityUIButton *vsButton = mainMenu->buttons[2];681vsButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_COMPETITION);682683foreach_all(UITAZoneModule, module) { module->disabled = !GameProgress_GetZoneUnlocked(module->zoneID); }684685int32 maxRounds = 0;686foreach_all(UIVsZoneButton, zoneButton)687{688zoneButton->xOut = !GameProgress_GetZoneUnlocked(zoneButton->zoneID);689zoneButton->obfuscate = zoneButton->xOut;690if (!zoneButton->xOut)691++maxRounds;692}693694EntityUIButton *matchLength = MenuSetup->competitionRules->buttons[1];695if (matchLength->choiceCount >= 1) {696EntityUIVsRoundPicker *vsRoundPicker = (EntityUIVsRoundPicker *)UIButton_GetChoicePtr(matchLength, matchLength->selection);697698if (vsRoundPicker->classID == UIVsRoundPicker->classID) {699vsRoundPicker->maxVal = maxRounds;700vsRoundPicker->val = MIN(vsRoundPicker->val, maxRounds);701}702}703704EntityUIControl *secrets = MenuSetup->secrets;705EntityUIButton *debugMode = secrets->buttons[0];706debugMode->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_DEBUGMODE);707if (debugMode->disabled)708UIButton_ManageChoices(debugMode);709710EntityUIButton *sonicAbility = secrets->buttons[1];711EntityUIButton *peeloutChoice = UIButton_GetChoicePtr(sonicAbility, 1);712EntityUIButton *instaShieldChoice = UIButton_GetChoicePtr(sonicAbility, 2);713714sonicAbility->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_PEELOUT);715if (sonicAbility->disabled)716UIButton_ManageChoices(sonicAbility);717718peeloutChoice->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_PEELOUT);719instaShieldChoice->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_INSTASHIELD);720721EntityUIButton *andKnux = secrets->buttons[2];722andKnux->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_ANDKNUX);723if (andKnux->disabled)724UIButton_ManageChoices(andKnux);725726EntityUIControl *extras = MenuSetup->extras;727728EntityUIButton *bssButton = extras->buttons[0];729bssButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_BLUESPHERES);730if (bssButton->disabled)731UIButton_ManageChoices(bssButton);732733EntityUIButton *puyoButton = extras->buttons[1];734puyoButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_MEANBEAN);735if (puyoButton->disabled)736UIButton_ManageChoices(puyoButton);737738EntityUIButton *daGardenButton = extras->buttons[2];739daGardenButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_DAGARDEN) && !globals->medallionDebug;740}741742void MenuSetup_HandleMenuReturn(void)743{744EntityMenuParam *param = MenuParam_GetParam();745746char buffer[0x100];747memset(buffer, 0, 0x100);748if (strcmp(param->menuTag, "") == 0)749UIUsernamePopup_ShowPopup();750751if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV)752MenuSetup_OptionsVideo_Win_MenuUpdateCB();753754foreach_all(UIControl, control)755{756if (strcmp(param->menuTag, "") != 0) {757RSDK.GetCString(buffer, &control->tag);758759if (strcmp((const char *)buffer, param->menuTag) != 0) {760UIControl_SetInactiveMenu(control);761}762else {763UIControl_SetActiveMenu(control);764control->buttonID = param->menuSelection;765766if (control == MenuSetup->timeAttackZones && param->startedTAAttempt)767UITAZoneModule_SetStartupModule(control, param->characterID, param->zoneID, param->actID, param->timeScore);768}769}770771if (control == MenuSetup->timeAttack && param->startedTAAttempt) {772int32 charID = param->characterID - 1;773control->buttonID = charID;774control->buttons[charID]->isSelected = true;775}776777if (control == MenuSetup->extras && param->puyoSelection == PUYO_SELECTION_VS_2P) {778UIButton_SetChoiceSelection(control->buttons[1], 1);779}780781if (control == MenuSetup->secrets) {782EntityUIControl *control = MenuSetup->secrets;783784UIButton_SetChoiceSelection(control->buttons[0], (globals->medalMods & MEDAL_ANDKNUCKLES) != 0);785786int32 medals = globals->medalMods;787if (medals & MEDAL_NODROPDASH) {788if (medals & MEDAL_PEELOUT)789UIButton_SetChoiceSelection(control->buttons[1], 1);790else if (medals & MEDAL_INSTASHIELD)791UIButton_SetChoiceSelection(control->buttons[1], 2);792}793else794UIButton_SetChoiceSelection(control->buttons[1], 0);795796UIButton_SetChoiceSelection(control->buttons[2], (globals->medalMods & MEDAL_ANDKNUCKLES) != 0);797}798799if (control == MenuSetup->video) {800EntityUIControl *control = MenuSetup->video;801EntityUIButton *button = control->buttons[0];802UIButton_SetChoiceSelection(button, RSDK.GetVideoSetting(VIDEOSETTING_SHADERID));803}804805if (control == MenuSetup->sound) {806EntityUIControl *control = MenuSetup->sound;807808EntityUISlider *slider = (EntityUISlider *)control->buttons[0];809slider->sliderPos = RSDK.GetVideoSetting(VIDEOSETTING_STREAM_VOL);810811slider = (EntityUISlider *)control->buttons[1];812slider->sliderPos = RSDK.GetVideoSetting(VIDEOSETTING_SFX_VOL);813}814815if (control == MenuSetup->language) {816EntityUIControl *control = MenuSetup->language;817818control->startingID = Localization->language;819control->buttonID = Localization->language;820}821822EntityCompetitionSession *session = CompetitionSession_GetSession();823if (session->inMatch) {824if (control == MenuSetup->competition) {825foreach_all(UIVsCharSelector, selector)826{827selector->prevFrameID = -1;828switch (session->playerID[selector->playerID]) {829case ID_SONIC: selector->frameID = 0; break;830case ID_TAILS: selector->frameID = 1; break;831case ID_KNUCKLES: selector->frameID = 2; break;832default: break;833}834}835}836837if (control == MenuSetup->competitionRules) {838switch (session->itemMode) {839case ITEMS_FIXED: UIButton_SetChoiceSelection(control->buttons[0], 0); break;840case ITEMS_RANDOM: UIButton_SetChoiceSelection(control->buttons[0], 2); break;841case ITEMS_TELEPORT: UIButton_SetChoiceSelection(control->buttons[0], 1); break;842}843844EntityUIVsRoundPicker *vsRoundPicker =845(EntityUIVsRoundPicker *)UIButton_GetChoicePtr(control->buttons[1], control->buttons[1]->selection);846if (vsRoundPicker)847vsRoundPicker->val = session->matchCount;848}849850if (control == MenuSetup->competitionZones) {851for (int32 i = 0; i < COMPETITION_STAGE_COUNT; ++i) {852EntityUIVsZoneButton *button = (EntityUIVsZoneButton *)control->buttons[i];853if (button && session->completedStages[i])854button->xOut = true;855}856}857}858}859860TimeAttackData_Clear();861}862863// Main Menu864int32 MenuSetup_GetActiveMenu(void)865{866EntityUIControl *control = UIControl_GetUIControl();867868if (control == MenuSetup->mainMenu || control == MenuSetup->extras || control == MenuSetup->options || control == MenuSetup->video869|| control == MenuSetup->sound || control == MenuSetup->controls_win || control == MenuSetup->controls_KB870|| control == MenuSetup->controls_PS4 || control == MenuSetup->controls_XB1 || control == MenuSetup->controls_NX871|| control == MenuSetup->controls_NX_Grip || control == MenuSetup->controls_NX_JoyCon || control == MenuSetup->controls_NX_Pro) {872return MAINMENU_MAIN;873}874875if (control == MenuSetup->timeAttack || control == MenuSetup->timeAttackZones || control == MenuSetup->leaderboards876|| control == MenuSetup->competition || control == MenuSetup->competitionRules || control == MenuSetup->competitionZones) {877return MAINMENU_TIMEATTACK;878}879880if (control == MenuSetup->competitionRound || control == MenuSetup->competitionTotal)881return MAINMENU_COMPETITION;882883if (control == MenuSetup->saveSelect || control == MenuSetup->noSaveMode || control == MenuSetup->secrets)884return MAINMENU_SAVESELECT;885886return MAINMENU_MAIN;887}888889void MenuSetup_ChangeMenuTrack(void)890{891int32 trackID = 0;892switch (MenuSetup_GetActiveMenu()) {893default:894case MAINMENU_MAIN: trackID = 0; break;895case MAINMENU_TIMEATTACK: trackID = 1; break;896case MAINMENU_COMPETITION: trackID = 2; break;897case MAINMENU_SAVESELECT: trackID = 3; break;898}899900if (!Music_IsPlaying())901Music_PlayTrack(trackID);902else if (Music->activeTrack != trackID)903Music_TransitionTrack(trackID, 0.12);904}905906void MenuSetup_SetBGColors(void)907{908switch (MenuSetup_GetActiveMenu()) {909case MAINMENU_MAIN: UIBackground->activeColors = UIBackground->bgColors; break;910911case MAINMENU_TIMEATTACK:912case MAINMENU_COMPETITION: UIBackground->activeColors = &UIBackground->bgColors[3]; break;913914case MAINMENU_SAVESELECT: UIBackground->activeColors = &UIBackground->bgColors[6]; break;915916default: break;917}918}919920void MenuSetup_MenuButton_ActionCB(void)921{922RSDK_THIS(UIModeButton);923924switch (self->buttonID) {925case 0: // Mania Mode926if (API_GetNoSave()) {927UIControl_MatchMenuTag("No Save Mode");928}929else {930MenuSetup->saveSelect->buttonID = 7;931UIControl_MatchMenuTag("Save Select");932}933break;934935case 1: // Time Attack936UIControl_MatchMenuTag("Time Attack");937break;938939case 2: // Competition940UIControl_MatchMenuTag("Competition");941break;942943case 3: // Options944UIControl_MatchMenuTag("Options");945break;946947default: return;948}949}950951bool32 MenuSetup_BackPressCB_ReturnToTitle(void)952{953MenuSetup_StartReturnToTitle();954955return true;956}957958void MenuSetup_StartReturnToTitle(void)959{960EntityUIControl *control = UIControl_GetUIControl();961if (control)962control->state = StateMachine_None;963964Music_FadeOut(0.05);965MenuSetup_StartTransition(MenuSetup_ReturnToTitle, 32);966}967968void MenuSetup_ReturnToTitle(void)969{970TimeAttackData_Clear();971972RSDK.SetScene("Presentation", "Title Screen");973RSDK.LoadScene();974}975976void MenuSetup_ExitGame(void) { APICallback_ExitGame(); }977978void MenuSetup_ExitGame_ActionCB(void)979{980String string;981INIT_STRING(string);982983#if GAME_VERSION != VER_100984Localization_GetString(&string, STR_QUITWARNING);985#else986Localization_GetString(&string, STR_QUITWARNINGLOSEPROGRESS);987#endif988UIDialog_CreateDialogYesNo(&string, MenuSetup_ExitGame_CB, NULL, true, true);989}990991void MenuSetup_ExitGame_CB(void)992{993if (UIControl_GetUIControl())994UIControl_GetUIControl()->state = StateMachine_None;995996Music_FadeOut(0.02);997MenuSetup_StartTransition(MenuSetup_ExitGame, 64);998}9991000void MenuSetup_State_HandleTransition(void)1001{1002RSDK_THIS(MenuSetup);10031004self->fadeTimer = CLAMP(self->timer << ((self->fadeShift & 0xFF) - 1), 0, 512);1005}10061007// Save Select1008int32 MenuSetup_GetMedalMods(void)1009{1010EntityUIControl *control = MenuSetup->secrets;10111012int32 mods = 0;1013if (control->buttons[0]->selection == 1)1014mods |= MEDAL_DEBUGMODE;10151016if (control->buttons[1]->selection == 1) {1017mods |= MEDAL_NODROPDASH;1018mods |= MEDAL_PEELOUT;1019}1020else if (control->buttons[1]->selection == 2) {1021mods |= MEDAL_NODROPDASH;1022mods |= MEDAL_INSTASHIELD;1023}10241025if (control->buttons[2]->selection == 1)1026mods |= MEDAL_ANDKNUCKLES;10271028return mods;1029}10301031void MenuSetup_OpenSaveSelectMenu(void)1032{1033EntityUIControl *control = MenuSetup->saveSelect;10341035UIControl_MatchMenuTag("Save Select");1036control->childHasFocus = false;1037}10381039void MenuSetup_SaveFileCB(void)1040{1041UIWaitSpinner_FinishWait();1042RSDK.LoadScene();1043}10441045void MenuSetup_SaveSlot_ActionCB(void)1046{1047RSDK_THIS(UISaveSlot);10481049SaveRAM *saveRAM = (SaveRAM *)SaveGame_GetDataPtr(self->slotID);10501051bool32 loadingSave = false;1052if (self->type) {1053// Bug Details(?):1054// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)1055// but the memset size is only 1024 (sizeof(uint8) * 0x400)1056// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal1057memset(globals->noSaveSlot, 0, 0x400);10581059globals->tempFlags = 0;1060globals->saveSlotID = NO_SAVE_SLOT;1061globals->gameMode = MODE_NOSAVE;1062globals->medalMods = MenuSetup_GetMedalMods();1063}1064else {1065globals->saveSlotID = self->slotID;1066globals->medalMods = 0;1067globals->gameMode = MODE_MANIA;10681069if (self->isNewSave) {1070int32 *saveData = SaveGame_GetDataPtr(self->slotID % 8);10711072// Bug Details(?):1073// see above1074memset(saveData, 0, 0x400);10751076saveRAM->saveState = 1;1077saveRAM->characterID = self->frameID;1078saveRAM->zoneID = 0;1079saveRAM->lives = 3;1080saveRAM->collectedEmeralds = self->saveEmeralds;1081saveRAM->continues = 0;10821083UIWaitSpinner_StartWait();1084loadingSave = true;1085SaveGame_SaveFile(MenuSetup_SaveFileCB);1086}1087else {1088if (saveRAM->saveState == SAVEGAME_COMPLETE) {1089SaveGame_ClearCollectedSpecialRings();1090saveRAM->score = 0;1091saveRAM->score1UP = 500000;1092}10931094loadingSave = true;1095SaveGame_SaveFile(MenuSetup_SaveFileCB);1096}1097}10981099switch (self->frameID) {1100case 0: // Sonic & Tails1101case 1: globals->playerID = ID_SONIC; break;11021103case 2: globals->playerID = ID_TAILS; break;11041105case 3: globals->playerID = ID_KNUCKLES; break;11061107default: break;1108}11091110if ((globals->medalMods & MEDAL_ANDKNUCKLES))1111globals->playerID |= ID_KNUCKLES_ASSIST;1112else if (!self->frameID)1113globals->playerID |= ID_TAILS_ASSIST;11141115if (self->type == UISAVESLOT_NOSAVE || self->isNewSave) {1116if (((globals->medalMods & MEDAL_DEBUGMODE) && (ControllerInfo->keyC.down || ControllerInfo->keyX.down))1117&& self->type == UISAVESLOT_NOSAVE)1118RSDK.SetScene("Presentation", "Level Select");1119else1120RSDK.SetScene("Cutscenes", "Angel Island Zone");1121}1122else {1123RSDK.SetScene("Mania Mode", "");1124SceneInfo->listPos += TimeAttackData_GetManiaListPos(self->saveZoneID, ACT_1, self->frameID);1125}11261127if (!loadingSave) {1128globals->initCoolBonus = false;1129RSDK.LoadScene();1130}1131}11321133void MenuSetup_SaveSel_MenuUpdateCB(void)1134{1135EntityUIControl *control = MenuSetup->saveSelect;11361137if (control->active == ACTIVE_ALWAYS) {1138EntityUIButtonPrompt *prompt = MenuSetup->delSavePrompt;11391140// buttonID == 8: No Save Slot Button1141if (control->lastButtonID == 8) {1142prompt->promptID = 6;1143prompt->buttonID = 3;1144}1145else {1146prompt->promptID = 3;1147prompt->buttonID = 2;1148}1149}1150}11511152void MenuSetup_OpenSecretsMenu(void)1153{1154EntityUIControl *control = MenuSetup->secrets;1155control->childHasFocus = false;11561157UIControl_MatchMenuTag("Secrets");1158}11591160void MenuSetup_SaveSel_YPressCB(void)1161{1162EntityUIControl *control = MenuSetup->saveSelect;11631164// buttonID == 8: No Save Slot Button1165if (control->active == ACTIVE_ALWAYS && control->buttonID == 8) {1166RSDK.PlaySfx(UIWidgets->sfxAccept, false, 0xFF);1167UIControl->inputLocked = true;11681169UITransition_StartTransition(MenuSetup_OpenSecretsMenu, 0);1170}1171}11721173void MenuSetup_TA_OpenZoneList_Sonic(void)1174{1175EntityMenuParam *param = MenuParam_GetParam();1176TimeAttackData_Clear();11771178param->characterID = 1;11791180EntityUIControl *control = MenuSetup->timeAttackZones;1181for (int32 i = 0; i < control->buttonCount; ++i) {1182EntityUITAZoneModule *button = (EntityUITAZoneModule *)control->buttons[i];1183button->characterID = param->characterID;1184}11851186UIControl_MatchMenuTag("Time Attack Zones");1187}11881189void MenuSetup_TA_OpenZoneList_Tails(void)1190{1191EntityMenuParam *param = MenuParam_GetParam();1192TimeAttackData_Clear();11931194param->characterID = 2;11951196EntityUIControl *control = MenuSetup->timeAttackZones;1197for (int32 i = 0; i < control->buttonCount; ++i) {1198EntityUITAZoneModule *button = (EntityUITAZoneModule *)control->buttons[i];1199button->characterID = param->characterID;1200}12011202UIControl_MatchMenuTag("Time Attack Zones");1203}12041205void MenuSetup_TA_OpenZoneList_Knux(void)1206{1207EntityMenuParam *param = MenuParam_GetParam();1208TimeAttackData_Clear();12091210param->characterID = 3;12111212EntityUIControl *control = MenuSetup->timeAttackZones;1213for (int32 i = 0; i < control->buttonCount; ++i) {1214EntityUITAZoneModule *button = (EntityUITAZoneModule *)control->buttons[i];1215button->characterID = param->characterID;1216}12171218UIControl_MatchMenuTag("Time Attack Zones");1219}12201221void MenuSetup_TA_TAZoneModule_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_TA_StartAttempt, 32); }12221223void MenuSetup_TA_StartAttempt(void)1224{1225EntityMenuParam *param = MenuParam_GetParam();12261227sprintf(param->menuTag, "Time Attack Zones");1228param->menuSelection = param->zoneID;1229param->startedTAAttempt = true;12301231SaveGame_ResetPlayerState();12321233// Bug Details(?):1234// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)1235// but the memset size is only 1024 (sizeof(uint8) * 0x400)1236// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal1237memset(globals->noSaveSlot, 0, 0x400);12381239globals->continues = 0;1240globals->saveSlotID = NO_SAVE_SLOT;1241globals->gameMode = MODE_TIMEATTACK;1242globals->medalMods = 0;12431244RSDK.SetScene("Mania Mode", "");1245SceneInfo->listPos += TimeAttackData_GetManiaListPos(param->zoneID, param->actID, param->characterID);12461247switch (param->characterID) {1248case 1: globals->playerID = ID_SONIC; break;1249case 2: globals->playerID = ID_TAILS; break;1250case 3: globals->playerID = ID_KNUCKLES; break;1251default: break;1252}12531254RSDK.LoadScene();1255}12561257void MenuSetup_TA_Leaderboards_TransitionCB(void)1258{1259EntityUIControl *leaderboardControl = MenuSetup->leaderboards;1260EntityUILeaderboard *leaderboards = MenuSetup->leaderboardWidget;12611262UIControl->forceBackPress = false;1263leaderboardControl->active = ACTIVE_NEVER;1264leaderboardControl->visible = false;1265leaderboardControl->state = StateMachine_None;12661267UIControl_SetActiveMenu(MenuSetup->timeAttackZones);1268UITAZoneModule_SetStartupModule(MenuSetup->timeAttackZones, leaderboards->characterID, leaderboards->zoneID, leaderboards->actID, 0);1269}12701271bool32 MenuSetup_TA_Leaderboards_BackPressCB(void)1272{1273UITransition_StartTransition(MenuSetup_TA_Leaderboards_TransitionCB, 0);12741275return true;1276}12771278void MenuSetup_TA_Leaderboards_YPressCB(void)1279{1280EntityUILeaderboard *leaderboards = MenuSetup->leaderboardWidget;12811282UITAZoneModule_ShowLeaderboards(leaderboards->characterID, leaderboards->zoneID, leaderboards->actID, leaderboards->viewingUserRank, NULL);1283}12841285void MenuSetup_State_SetupLeaderboards(void)1286{1287RSDK_THIS(MenuSetup);12881289EntityUIDialog *dialog = MenuSetup->connectingDlg;1290EntityUILeaderboard *leaderboard = MenuSetup->leaderboardWidget;1291EntityUIButtonPrompt *prompt = MenuSetup->leaderboardPrompt;12921293int32 status = APICallback_LeaderboardStatus();12941295if (status == STATUS_CONTINUE) {1296String message;1297INIT_STRING(message);1298RSDK.InitString(&message, "", 0);12991300Localization_GetString(&message, STR_CONNECTING);1301UIDialog_SetupText(dialog, &message);1302}1303else if (status >= STATUS_ERROR) {1304status = APICallback_LeaderboardStatus();13051306int32 strID = status == STATUS_TIMEOUT ? STR_COMMERROR : STR_NOWIFI;13071308String message;1309INIT_STRING(message);1310RSDK.InitString(&message, "", 0);1311Localization_GetString(&message, strID);13121313UIDialog_SetupText(dialog, &message);1314UIDialog_AddButton(DIALOG_OK, dialog, NULL, true);13151316EntityUIControl *parent = dialog->parent;1317parent->rowCount = 1;1318parent->columnCount = 1;1319parent->buttonID = 0;13201321if (leaderboard->taRecord)1322leaderboard->viewingUserRank = !leaderboard->viewingUserRank;13231324prompt->promptID = leaderboard->viewingUserRank ? 14 : 15;1325prompt->prevPrompt = -1;1326prompt->visible = leaderboard->taRecord != 0;13271328self->callback = StateMachine_None;1329MenuSetup->connectingDlg = NULL;1330destroyEntity(self);1331}1332else if (status == STATUS_OK) {1333prompt->promptID = leaderboard->viewingUserRank ? 14 : 15;1334prompt->prevPrompt = -1;1335prompt->visible = leaderboard->taRecord != 0;13361337UILeaderboard_InitLeaderboard(leaderboard);1338UIDialog_CloseOnSel_HandleSelection(dialog, self->callback);13391340self->callback = StateMachine_None;1341MenuSetup->connectingDlg = NULL;1342destroyEntity(self);1343}1344}13451346// Competition1347void MenuSetup_VS_OpenCompRules(void) { UIControl_MatchMenuTag("Competition Rules"); }1348void MenuSetup_VS_OpenCompZones(void) { UIControl_MatchMenuTag("Competition Zones"); }13491350void MenuSetup_VS_ProcessButtonCB(void)1351{1352EntityUIControl *control = MenuSetup->competition;13531354if (control) {1355bool32 allPlayersReady = true;13561357foreach_all(UIVsCharSelector, charSel)1358{1359Entity *entStore = SceneInfo->entity;1360SceneInfo->entity = (Entity *)charSel;1361StateMachine_Run(charSel->processButtonCB);1362SceneInfo->entity = entStore;13631364if (allPlayersReady)1365allPlayersReady = charSel->ready ? !charSel->isSelected : false;1366}13671368if (allPlayersReady) {1369control->selectionDisabled = true;1370UITransition_StartTransition(MenuSetup_VS_OpenCompRules, 0);1371}1372}1373}13741375void MenuSetup_VS_MenuSetupCB(void)1376{1377RSDK_THIS(UIControl);13781379self->childHasFocus = false;13801381foreach_all(UIVsCharSelector, charSel)1382{1383charSel->isSelected = true;1384charSel->ready = false;1385charSel->processButtonCB = UIVsCharSelector_ProcessButtonCB;1386}1387}13881389void MenuSetup_VS_StartMatch(void)1390{1391EntityCompetitionSession *session = CompetitionSession_GetSession();1392EntityMenuParam *param = MenuParam_GetParam();13931394sprintf(param->menuTag, "Competition Round");1395session->stageIndex = MenuSetup->competitionZones->buttonID;1396session->zoneID = param->vsZoneID;1397session->actID = param->vsActID;13981399RSDK.SetScene("Mania Mode", "");1400SceneInfo->listPos += TimeAttackData_GetManiaListPos(param->vsZoneID, param->vsActID, CHAR_SONIC);14011402SaveGame_ResetPlayerState();14031404// Bug Details(?):1405// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)1406// but the memset size is only 1024 (sizeof(uint8) * 0x400)1407// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal1408memset(globals->noSaveSlot, 0, 0x400);14091410globals->continues = 0;1411globals->saveSlotID = NO_SAVE_SLOT;1412globals->gameMode = MODE_COMPETITION;1413globals->medalMods = 0;14141415globals->playerID = ID_NONE;1416for (int32 i = 0; i < COMPETITION_PLAYER_COUNT; ++i) globals->playerID |= session->playerID[i] << (8 * i);14171418globals->itemMode = session->itemMode;14191420RSDK.LoadScene();1421}14221423void MenuSetup_VS_StartMatch_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_VS_StartMatch, 32); }14241425void MenuSetup_VS_RulesButton_ActionCB(void)1426{1427EntityUIControl *compControl = MenuSetup->competition;1428EntityUIControl *rulesControl = MenuSetup->competitionRules;1429EntityCompetitionSession *session = CompetitionSession_GetSession();14301431int32 matchCount = 0;1432foreach_all(UIVsRoundPicker, vsRoundPicker)1433{1434matchCount = vsRoundPicker->val;1435foreach_break;1436}14371438int32 itemMode = ITEMS_FIXED;1439switch (rulesControl->buttons[0]->selection) {1440default: break;1441case 0: itemMode = ITEMS_FIXED; break;1442case 1: itemMode = ITEMS_TELEPORT; break;1443case 2: itemMode = ITEMS_RANDOM; break;1444}14451446CompetitionSession_ResetOptions();14471448session->matchCount = matchCount;1449session->inMatch = true;1450session->itemMode = itemMode;14511452session->playerCount = 2;14531454EntityUIVsCharSelector *charSel = (EntityUIVsCharSelector *)compControl->buttons[0];1455switch (charSel->frameID) {1456case 0: session->playerID[0] = ID_SONIC; break;1457case 1: session->playerID[0] = ID_TAILS; break;1458case 2: session->playerID[0] = ID_KNUCKLES; break;1459default: break;1460}14611462charSel = (EntityUIVsCharSelector *)compControl->buttons[1];1463switch (charSel->frameID) {1464case 0: session->playerID[1] = ID_SONIC; break;1465case 1: session->playerID[1] = ID_TAILS; break;1466case 2: session->playerID[1] = ID_KNUCKLES; break;1467default: break;1468}14691470EntityUIControl *zoneControl = MenuSetup->competitionZones;1471zoneControl->position = zoneControl->startPos;1472zoneControl->targetPos.x = zoneControl->startPos.x;1473zoneControl->targetPos.y = zoneControl->startPos.y;1474zoneControl->buttonID = 0;14751476foreach_all(UIVsZoneButton, zoneButton)1477{1478zoneButton->xOut = !GameProgress_GetZoneUnlocked(zoneButton->zoneID);1479zoneButton->obfuscate = zoneButton->xOut;1480}14811482UIControl_MatchMenuTag("Competition Zones");1483}14841485void MenuSetup_VS_OpenCompTotal(void) { UIControl_MatchMenuTag("Competition Total"); }14861487void MenuSetup_VS_Round_ProcessButtonCB(void)1488{1489EntityCompetitionSession *session = CompetitionSession_GetSession();14901491if (UIControl->confirmPress[0] || UIControl->confirmPress[1] || UIControl->confirmPress[2] || UIControl->confirmPress[3]) {1492bool32 toCompTotal = false;14931494int32 activePlayers = 0;1495for (int32 p = 0; p < COMPETITION_PLAYER_COUNT; ++p) {1496if (session->lives[p] > 0)1497activePlayers++;14981499if (session->wins[p] > (session->matchCount >> 1))1500toCompTotal = true;1501}15021503if (toCompTotal || activePlayers < 2 || session->matchID >= session->matchCount)1504UITransition_StartTransition(MenuSetup_VS_OpenCompTotal, 0);1505else1506UITransition_StartTransition(MenuSetup_VS_OpenCompZones, 0);15071508RSDK.PlaySfx(UIWidgets->sfxAccept, false, 255);1509UIControl->inputLocked = true;1510}1511}15121513void MenuSetup_VS_Round_MenuSetupCB(void)1514{1515EntityCompetitionSession *session = CompetitionSession_GetSession();1516EntityUIControl *roundControl = MenuSetup->competitionRound;15171518int32 matchWinner = session->matchWinner[session->matchID - 1];15191520int32 winner = 0;1521if (matchWinner > 1)1522winner = matchWinner - 1;15231524String roundLabelStr;1525INIT_STRING(roundLabelStr);15261527char roundLabel[0x100];1528memset(roundLabel, 0, sizeof(roundLabel));15291530Localization_GetZoneName(&roundLabelStr, session->zoneID);1531if (session->zoneID < 12) {1532char buf[16];1533sprintf(buf, " ZONE %d", session->actID + 1);1534RSDK.AppendText(&roundLabelStr, buf);1535}15361537RSDK.GetCString(roundLabel, &roundLabelStr);1538UIInfoLabel_SetText(MenuSetup->roundLabel, roundLabel);15391540EntityUIVsScoreboard *scoreboard = MenuSetup->roundScoreboard;1541UIVsScoreboard_SetScores(scoreboard, session->wins[0], session->wins[1]);1542scoreboard->showWinner = matchWinner != 0;1543scoreboard->winnerID = winner;15441545if (matchWinner) {1546LogHelpers_Print("Announce_CharWins(%d)", session->playerID[winner]);15471548EntityAnnouncer *announcer = CREATE_ENTITY(Announcer, NULL, 0, 0);1549announcer->state = Announcer_State_AnnounceWinPlayer;1550announcer->playerID = session->playerID[winner];1551}15521553uint32 times[PLAYER_COUNT];1554for (int32 p = 0; p < COMPETITION_PLAYER_COUNT; ++p) {1555times[p] = session->time[p].milliseconds + 100 * (session->time[p].seconds + 4 * (16 * session->time[p].minutes - session->time[p].minutes));1556}15571558char buffer[0x40];1559foreach_all(UIVsResults, results)1560{1561if (UIControl_ContainsPos(roundControl, &results->position)) {1562int32 p = results->playerID;1563int32 r = results->playerID ^ 1;15641565results->isWinner = p == winner && scoreboard->showWinner;15661567memset(buffer, 0, sizeof(buffer));15681569sprintf(buffer, "%d", session->rings[p]);1570if (!SceneInfo->inEditor) {1571RSDK.InitString(&results->rowText[0], buffer, 0);1572RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[0]);1573}15741575sprintf(buffer, "%d", session->totalRings[p]);1576if (!SceneInfo->inEditor) {1577RSDK.InitString(&results->rowText[1], buffer, 0);1578RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[1]);1579}15801581sprintf(buffer, "%d", session->score[p]);1582if (!SceneInfo->inEditor) {1583RSDK.InitString(&results->rowText[2], buffer, 0);1584RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[2]);1585}15861587sprintf(buffer, "%d", session->items[p]);1588if (!SceneInfo->inEditor) {1589RSDK.InitString(&results->rowText[3], buffer, 0);1590RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[3]);1591}15921593sprintf(buffer, "%d'%02d\"%02d", session->time[p].minutes, session->time[p].seconds, session->time[p].milliseconds);1594if (!SceneInfo->inEditor) {1595RSDK.InitString(&results->rowText[4], buffer, 0);1596RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[4]);1597}15981599if (session->lives[p]) {1600if (session->lives[r]) {1601results->row0Highlight = session->rings[p] > session->rings[r];1602results->row1Highlight = session->totalRings[p] > session->totalRings[r];1603results->row2Highlight = session->score[p] > session->score[r];1604results->row3Highlight = session->items[p] > session->items[r];1605results->row4Highlight = times[p] > 0 && times[p] < times[r];1606}1607else {1608results->row0Highlight = true;1609results->row1Highlight = true;1610results->row2Highlight = true;1611results->row3Highlight = true;1612results->row4Highlight = true;1613}1614}1615}1616}1617}16181619void MenuSetup_VS_GotoCompetition(void) { UIControl_MatchMenuTag("Competition"); }16201621void MenuSetup_VS_Total_ProcessButtonCB(void)1622{1623EntityCompetitionSession *session = CompetitionSession_GetSession();16241625if (UIControl->anyConfirmPress) {1626int32 mostWins = 0;1627for (int32 p = 0; p < session->playerCount; ++p) {1628if (session->wins[p] > mostWins)1629mostWins = session->wins[p];1630}16311632int32 winnerCount = 0;1633for (int32 p = 0; p < session->playerCount; ++p) {1634if (session->wins[p] == mostWins)1635winnerCount++;1636}16371638if (winnerCount > 1) {1639MenuSetup_StartTransition(MenuSetup_VS_StartPuyoMatch, 32);1640}1641else {1642CompetitionSession_ResetOptions();1643UITransition_StartTransition(MenuSetup_VS_GotoCompetition, 0);1644}16451646RSDK.PlaySfx(UIWidgets->sfxAccept, false, 255);1647UIControl->inputLocked = true;1648}1649}16501651void MenuSetup_VS_Total_MenuSetupCB(void)1652{1653EntityUIControl *totalControl = MenuSetup->competitionTotal;1654EntityCompetitionSession *session = CompetitionSession_GetSession();16551656MenuSetup->vsTotalTimer = 120;16571658totalControl->targetPos.y = totalControl->startPos.y;1659totalControl->position.y = totalControl->startPos.y;16601661String string;1662INIT_STRING(string);16631664EntityUIInfoLabel *label = MenuSetup->totalLabel;1665Localization_GetString(&string, STR_COMPTOTAL);1666UIInfoLabel_SetString(label, &string);16671668int32 highestScore = 0;1669for (int32 p = 0; p < session->playerCount; ++p) {1670if (session->wins[p] > highestScore)1671highestScore = session->wins[p];1672}16731674EntityUIVsScoreboard *scoreboard = MenuSetup->roundScoreboard;1675UIVsScoreboard_SetScores(scoreboard, session->wins[0], session->wins[1]);1676scoreboard->showWinner = session->wins[0] != session->wins[1];1677scoreboard->winnerID = session->wins[1] > session->wins[0];16781679if (scoreboard->showWinner) {1680LogHelpers_Print("Announce_WinnerIs(%d)", scoreboard->winnerID);1681EntityAnnouncer *announcer = CREATE_ENTITY(Announcer, NULL, 0, 0);1682announcer->state = Announcer_State_AnnounceWinner;1683announcer->playerID = scoreboard->winnerID;1684}16851686foreach_all(UIVsResults, results)1687{1688if (UIControl_ContainsPos(totalControl, &results->position)) {1689bool32 *highlight = &results->row0Highlight;16901691results->numRows = session->matchCount;1692results->isWinner = results->playerID == scoreboard->winnerID;16931694for (int32 r = 0; r < results->numRows; ++r) {1695char buffer[0x40];1696sprintf(buffer, "%d", session->matchWinner[r]);16971698if (!SceneInfo->inEditor) {1699RSDK.InitString(&results->rowText[r], buffer, 0);1700RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[r]);1701}17021703highlight[r] = false;1704if (session->matchWinner[r])1705highlight[r] = (session->matchWinner[r] - 1) == results->playerID;1706}1707}1708}1709}17101711void MenuSetup_VS_Total_MenuUpdateCB(void)1712{1713EntityUIControl *totalControl = MenuSetup->competitionTotal;17141715if (totalControl->active == ACTIVE_ALWAYS) {1716if (totalControl->position.y == totalControl->targetPos.y) {1717if (MenuSetup->vsTotalTimer <= 0) {1718int32 targetPos = totalControl->startPos.y;1719if (totalControl->targetPos.y == totalControl->startPos.y) {1720EntityUIVsResults *button = (EntityUIVsResults *)totalControl->buttons[0];17211722if (button && button->size.y + button->position.y - 0x708000 > totalControl->startPos.y) {1723targetPos = button->size.y + button->position.y - 0x708000;1724}1725}17261727totalControl->targetPos.y = targetPos;1728MenuSetup->vsTotalTimer = 120;1729}1730else {1731MenuSetup->vsTotalTimer--;1732}1733}1734}1735}17361737void MenuSetup_VS_ExitComp_TransitionCB(void)1738{1739EntityUIControl *control = MenuSetup->competition;1740EntityUIControl *zoneControl = MenuSetup->competitionZones;17411742UIControl_SetInactiveMenu(zoneControl);1743UIControl_SetActiveMenu(control);1744CompetitionSession_ResetOptions();17451746zoneControl->childHasFocus = false;17471748foreach_all(UIVsZoneButton, zoneButton)1749{1750zoneButton->xOut = !GameProgress_GetZoneUnlocked(zoneButton->zoneID);1751zoneButton->obfuscate = zoneButton->xOut;1752}1753}17541755void MenuSetup_VS_BackoutFromVsCharSelect_CB(void)1756{1757EntityUIControl *control = UIControl_GetUIControl();1758control->selectionDisabled = false;17591760UIControl_HandleMenuChange(&control->parentTag);1761}17621763bool32 MenuSetup_VS_BackoutFromVsCharSelect(void)1764{1765LogHelpers_Print("BackoutFromVsCharSelect()");1766EntityUIControl *control = MenuSetup->competition;17671768for (int32 i = 0; i < control->buttonCount; ++i) {1769EntityUIVsCharSelector *button = (EntityUIVsCharSelector *)control->buttons[i];1770if (button->classID == UIVsCharSelector->classID && button->prevSelected && UIControl->backPress[button->playerID]) {1771UITransition_StartTransition(MenuSetup_VS_BackoutFromVsCharSelect_CB, 0);1772return true;1773}1774}17751776if (!control->buttonCount) {1777control->selectionDisabled = true;17781779if (!UIControl->backPress[0] && UIControl->anyBackPress) {1780UITransition_StartTransition(MenuSetup_VS_BackoutFromVsCharSelect_CB, 0);1781return true;1782}1783}17841785return false;1786}17871788void MenuSetup_VS_ExitComp_YesCB(void) { UITransition_StartTransition(MenuSetup_VS_ExitComp_TransitionCB, 0); }17891790bool32 MenuSetup_VS_CompZones_BackPressCB(void)1791{1792String message;1793INIT_STRING(message);17941795Localization_GetString(&message, STR_EXITCOMP);1796UIDialog_CreateDialogYesNo(&message, MenuSetup_VS_ExitComp_YesCB, NULL, true, true);17971798return true;1799}18001801void MenuSetup_VS_StartPuyoMatch(void)1802{1803EntityMenuParam *param = MenuParam_GetParam();18041805TimeAttackData_Clear();18061807param->puyoSelection = PUYO_SELECTION_TIE_BREAKER;1808globals->gameMode = MODE_COMPETITION;1809strcpy(param->menuTag, "Competition Total");1810param->menuSelection = 0;18111812RSDK.SetScene("Extras", "Puyo Puyo");1813RSDK.LoadScene();1814}18151816// Options1817void MenuSetup_Options_VideoMenuButton_ActionCB(void)1818{1819if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV)1820UIControl_MatchMenuTag("Video WIN");1821else1822UIControl_MatchMenuTag("Video");1823}18241825void MenuSetup_Options_SoundMenuButton_ActionCB(void) { UIControl_MatchMenuTag("Sound"); }18261827void MenuSetup_Options_LanguageMenuButton_ActionCB(void) { UIControl_MatchMenuTag("Language"); }18281829void MenuSetup_Options_ControlsMenuButton_ActionCB(void)1830{1831int32 id = API_GetFilteredInputDeviceID(INPUT_NONE);1832int32 type = API_GetInputDeviceType(id);18331834switch (sku_platform) {1835case PLATFORM_DEV:1836case PLATFORM_PC:1837if (sku_platform == PLATFORM_DEV || type)1838UIControl_MatchMenuTag("Controls WIN");1839else1840UIControl_MatchMenuTag("Controls XB1");1841break;18421843case PLATFORM_PS4: UIControl_MatchMenuTag("Controls PS4"); break;18441845case PLATFORM_XB1: UIControl_MatchMenuTag("Controls XB1"); break;18461847case PLATFORM_SWITCH:1848switch (type) {1849case 1: UIControl_MatchMenuTag("Controls NX"); break;1850case 2: UIControl_MatchMenuTag("Controls NX Grip"); break;1851case 3: UIControl_MatchMenuTag("Controls NX Joycon"); break;1852case 4: UIControl_MatchMenuTag("Controls NX Pro"); break;1853default: break;1854}1855break;1856}1857}18581859void MenuSetup_Options_SetDefaultMappings_P1(void)1860{1861ControllerInfo[CONT_P1].keyUp.keyMap = KEYMAP_UP;1862ControllerInfo[CONT_P1].keyDown.keyMap = KEYMAP_DOWN;1863ControllerInfo[CONT_P1].keyLeft.keyMap = KEYMAP_LEFT;1864ControllerInfo[CONT_P1].keyRight.keyMap = KEYMAP_RIGHT;1865ControllerInfo[CONT_P1].keyA.keyMap = KEYMAP_A;1866ControllerInfo[CONT_P1].keyB.keyMap = KEYMAP_S;1867ControllerInfo[CONT_P1].keyC.keyMap = KEYMAP_NO_MAPPING;1868ControllerInfo[CONT_P1].keyX.keyMap = KEYMAP_Q;1869ControllerInfo[CONT_P1].keyY.keyMap = KEYMAP_W;1870ControllerInfo[CONT_P1].keyZ.keyMap = KEYMAP_NO_MAPPING;1871ControllerInfo[CONT_P1].keyStart.keyMap = KEYMAP_RETURN;1872ControllerInfo[CONT_P1].keySelect.keyMap = KEYMAP_TAB;1873}18741875void MenuSetup_Options_SetDefaultMappings_P2(void)1876{1877#if GAME_VERSION != VER_1001878ControllerInfo[CONT_P2].keyUp.keyMap = KEYMAP_NUMPAD8;1879ControllerInfo[CONT_P2].keyDown.keyMap = KEYMAP_NUMPAD5;1880ControllerInfo[CONT_P2].keyLeft.keyMap = KEYMAP_NUMPAD4;1881ControllerInfo[CONT_P2].keyRight.keyMap = KEYMAP_NUMPAD6;1882ControllerInfo[CONT_P2].keyA.keyMap = KEYMAP_J;1883ControllerInfo[CONT_P2].keyB.keyMap = KEYMAP_K;1884ControllerInfo[CONT_P2].keyC.keyMap = KEYMAP_NO_MAPPING;1885ControllerInfo[CONT_P2].keyX.keyMap = KEYMAP_U;1886ControllerInfo[CONT_P2].keyY.keyMap = KEYMAP_I;1887ControllerInfo[CONT_P2].keyZ.keyMap = KEYMAP_NO_MAPPING;1888ControllerInfo[CONT_P2].keyStart.keyMap = KEYMAP_OEM_4;1889ControllerInfo[CONT_P2].keySelect.keyMap = KEYMAP_OEM_6;1890#else1891ControllerInfo[CONT_P2].keyUp.keyMap = KEYMAP_I;1892ControllerInfo[CONT_P2].keyDown.keyMap = KEYMAP_K;1893ControllerInfo[CONT_P2].keyLeft.keyMap = KEYMAP_J;1894ControllerInfo[CONT_P2].keyRight.keyMap = KEYMAP_L;1895ControllerInfo[CONT_P2].keyA.keyMap = KEYMAP_V;1896ControllerInfo[CONT_P2].keyB.keyMap = KEYMAP_B;1897ControllerInfo[CONT_P2].keyC.keyMap = KEYMAP_NO_MAPPING;1898ControllerInfo[CONT_P2].keyX.keyMap = KEYMAP_F;1899ControllerInfo[CONT_P2].keyY.keyMap = KEYMAP_G;1900ControllerInfo[CONT_P2].keyZ.keyMap = KEYMAP_NO_MAPPING;1901ControllerInfo[CONT_P2].keyStart.keyMap = KEYMAP_O;1902ControllerInfo[CONT_P2].keySelect.keyMap = KEYMAP_NO_MAPPING;1903#endif1904}19051906void MenuSetup_Options_SetupKBControlsMenu(int32 playerID)1907{1908EntityUIControl *control = MenuSetup->controls_KB;19091910foreach_all(UISubHeading, subHeading)1911{1912if (UIControl_ContainsPos(control, &subHeading->position)) {1913subHeading->frameID = playerID + 8;1914foreach_break;1915}1916}19171918for (int32 b = 0; b < control->buttonCount; ++b) {1919if (control->buttons[b]->classID == UIKeyBinder->classID) {1920EntityUIKeyBinder *binder = (EntityUIKeyBinder *)control->buttons[b];1921binder->inputID = playerID;1922}1923else if (control->buttons[b]->classID == UIButton->classID) {1924EntityUIButton *button = control->buttons[b];19251926if (playerID == 1)1927button->actionCB = MenuSetup_Options_SetDefaultMappings_P2;1928else if (playerID == 0)1929button->actionCB = MenuSetup_Options_SetDefaultMappings_P1;1930}1931}1932}19331934void MenuSetup_OptionsVideo_Win_MenuUpdateCB(void) { MenuSetup_OptionsVideo_Win_InitVideoOptionsMenu(); }19351936void MenuSetup_OptionsVideo_Win_InitVideoOptionsMenu(void)1937{1938if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV) {1939EntityUIControl *videoControl_Win = MenuSetup->video_win;1940OptionsRAM *optionsRAM = Options_GetOptionsRAM();1941Options_GetWinSize();19421943int32 options[7];19441945#if GAME_VERSION != VER_1001946options[0] = RSDK.GetVideoSetting(VIDEOSETTING_SHADERID); // filter1947options[1] = optionsRAM->windowSize; // window size1948options[2] = RSDK.GetVideoSetting(VIDEOSETTING_BORDERED); // bordered19491950options[3] = 0;1951if (!RSDK.GetVideoSetting(VIDEOSETTING_WINDOWED) || optionsRAM->windowSize == 4)1952options[3] = 1;19531954options[4] = 0; // fullscreen res1955options[5] = RSDK.GetVideoSetting(VIDEOSETTING_VSYNC); // vsync1956options[6] = RSDK.GetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED); // triple buffered1957#else1958options[0] = RSDK.GetVideoSetting(VIDEOSETTING_SHADERID); // filter1959options[1] = optionsRAM->windowSize; // window size1960options[2] = RSDK.GetVideoSetting(VIDEOSETTING_BORDERED); // bordered19611962options[3] = 0;1963if (!RSDK.GetVideoSetting(VIDEOSETTING_WINDOWED) || optionsRAM->windowSize == 4)1964options[3] = 1;19651966options[4] = RSDK.GetVideoSetting(VIDEOSETTING_VSYNC); // vsync1967options[5] = RSDK.GetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED); // triple buffered1968#endif19691970for (int32 i = 0; i < videoControl_Win->buttonCount; ++i) {1971EntityUIButton *button = videoControl_Win->buttons[i];19721973#if GAME_VERSION != VER_1001974if (i == 4) {1975EntityUIResPicker *resPicker = (EntityUIResPicker *)UIButton_GetChoicePtr(button, button->selection);1976UIResPicker_GetDisplayInfo(resPicker);1977}1978else if (i == 1) {1979EntityUIWinSize *winSize = (EntityUIWinSize *)UIButton_GetChoicePtr(button, button->selection);1980winSize->selection = RSDK.GetVideoSetting(VIDEOSETTING_WINDOW_HEIGHT) / SCREEN_YSIZE;1981}1982else if (button->selection != options[i]) {1983UIButton_SetChoiceSelection(button, options[i]);1984}1985#else1986if (button->selection != options[i]) {1987UIButton_SetChoiceSelection(button, options[i]);1988}1989#endif1990}1991}1992}19931994void MenuSetup_Options_OpenKBControlsMenu(void)1995{1996RSDK_THIS(UIButton);19971998EntityUIControl *control = MenuSetup->controls_win;19992000for (int32 i = 0; i < control->buttonCount; ++i) {2001if (self == control->buttons[i]) {2002MenuSetup_Options_SetupKBControlsMenu(i);2003UIControl_MatchMenuTag("Controls KB");2004break;2005}2006}2007}20082009void MenuSetup_Options_MenuSetupCB(void)2010{2011if (Options->changed) {2012UIWaitSpinner_StartWait();20132014Options_SaveFile(MenuSetup_Options_SaveOptionsCB_Load);2015}2016}20172018void MenuSetup_Options_SaveOptionsCB_Load(void) { UIWaitSpinner_FinishWait(); }20192020void MenuSetup_Options_LaunchManual(void)2021{2022RSDK.PlaySfx(UIWidgets->sfxAccept, false, 0xFF);2023API_LaunchManual();2024}20252026void MenuSetup_OptionsLanguage_LanguageButton_ActionCB(void)2027{2028OptionsRAM *options = Options_GetOptionsRAM();2029EntityUIControl *control = MenuSetup->language;20302031if (control->buttonID < 0)2032options->language = -1;2033else2034options->language = control->buttonID;20352036options->overrideLanguage = control->buttonID >= 0;20372038if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV)2039RSDK.SetVideoSetting(VIDEOSETTING_LANGUAGE, control->buttonID);20402041Options->changed = true;20422043Localization->language = control->buttonID;2044control->startingID = control->buttonID;2045Localization->loaded = false;20462047Localization_LoadStrings();2048UIWidgets_ApplyLanguage();2049UIHeading_LoadSprites();20502051UIControl_MatchMenuTag("Options");2052}20532054void MenuSetup_OptionsVideo_ShaderButton_ActionCB(void)2055{2056RSDK_THIS(UIButton);20572058OptionsRAM *options = Options_GetOptionsRAM();20592060options->screenShader = self->selection;2061options->overrideShader = true;2062RSDK.SetVideoSetting(VIDEOSETTING_SHADERID, self->selection);20632064Options->changed = true;2065}20662067void MenuSetup_OptionsVideo_WindowScaleButton_ActionCB(void)2068{2069RSDK_THIS(UIButton);20702071OptionsRAM *options = Options_GetOptionsRAM();20722073if (self->selection != 4) {2074RSDK.SetVideoSetting(VIDEOSETTING_WINDOW_WIDTH, WIDE_SCR_XSIZE * (self->selection + 1));2075RSDK.SetVideoSetting(VIDEOSETTING_WINDOW_HEIGHT, SCREEN_YSIZE * (self->selection + 1));20762077options->windowSize = self->selection;2078Options->changed = true;2079}2080}20812082void MenuSetup_OptionsVideo_BorderlessButton_ActionCB(void)2083{2084RSDK_THIS(UIButton);20852086OptionsRAM *options = Options_GetOptionsRAM();20872088options->windowBorder = self->selection;2089RSDK.SetVideoSetting(VIDEOSETTING_BORDERED, self->selection);20902091RSDK.UpdateWindow();2092Options->changed = true;2093}20942095void MenuSetup_OptionsVideo_FullscreenButton_ActionCB(void)2096{2097RSDK_THIS(UIButton);20982099OptionsRAM *options = Options_GetOptionsRAM();21002101options->windowed = self->selection ^ 1;2102RSDK.SetVideoSetting(VIDEOSETTING_WINDOWED, options->windowed);21032104RSDK.UpdateWindow();2105Options->changed = true;2106}21072108void MenuSetup_OptionsVideo_VSyncButton_ActionCB(void)2109{2110RSDK_THIS(UIButton);21112112OptionsRAM *options = Options_GetOptionsRAM();21132114options->vSync = self->selection;2115RSDK.SetVideoSetting(VIDEOSETTING_VSYNC, self->selection);21162117Options->changed = true;2118}21192120void MenuSetup_OptionsVideo_TripleBufferButton_ActionCB(void)2121{2122RSDK_THIS(UIButton);21232124OptionsRAM *options = Options_GetOptionsRAM();21252126options->tripleBuffering = self->selection;2127RSDK.SetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED, self->selection);21282129Options->changed = true;2130}21312132void MenuSetup_OptionsVideo_UISlider_ChangedCB(void)2133{2134RSDK_THIS(UISlider);21352136OptionsRAM *options = Options_GetOptionsRAM();21372138// Bug Details (?):2139// what the hell is up with this???????2140// it'd only ever be 0 or 1 why are 0xF1, 0xF2, 0xF4, 0xF5 & 0xFC options?????2141// this is a CB for the slider why are the boolean values here???21422143bool32 value = self->frameID != 1;2144switch (value) {2145case 0xF1:2146options->windowed = self->sliderPos;2147RSDK.SetVideoSetting(VIDEOSETTING_WINDOWED, options->windowed);2148break;21492150case 0xF2:2151options->windowBorder = self->sliderPos;2152RSDK.SetVideoSetting(VIDEOSETTING_BORDERED, options->windowBorder);2153break;21542155case 0xF4:2156options->vSync = self->sliderPos;2157RSDK.SetVideoSetting(VIDEOSETTING_VSYNC, options->vSync);2158break;21592160case 0xF5:2161options->tripleBuffering = self->sliderPos;2162RSDK.SetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED, options->tripleBuffering);2163break;21642165case 0xFC:2166options->screenShader = self->sliderPos;2167options->overrideShader = true;2168RSDK.SetVideoSetting(VIDEOSETTING_SHADERID, options->screenShader);21692170RSDK.UpdateWindow();2171break;21722173case 0:2174options->volMusic = self->sliderPos;2175options->overrideMusicVol = true;2176RSDK.SetVideoSetting(VIDEOSETTING_STREAM_VOL, options->volMusic);2177break;21782179case 1:2180options->volSfx = self->sliderPos;2181options->overrideSfxVol = true;2182RSDK.SetVideoSetting(VIDEOSETTING_SFX_VOL, options->volSfx);2183break;21842185default: break;2186}2187Options->changed = true;2188}21892190void MenuSetup_OpenExtrasMenu_ActionCB(void) { UIControl_MatchMenuTag("Extras"); }21912192// Extras2193void MenuSetup_Extras_ProcessButtonCB(void) { UIControl_ProcessButtonInput(); }21942195void MenuSetup_Extras_Start_Puyo_vsAI(void)2196{2197EntityMenuParam *param = MenuParam_GetParam();21982199TimeAttackData_Clear();22002201param->puyoSelection = PUYO_SELECTION_VS_CPU;2202strcpy(param->menuTag, "Extras");2203param->menuSelection = EXTRAS_SELECTION_PUYO;22042205RSDK.SetScene("Extras", "Puyo Puyo");2206RSDK.LoadScene();2207}22082209void MenuSetup_Extras_Puyo_vsAI_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_Puyo_vsAI, 32); }22102211void MenuSetup_Extras_Start_Puyo_vs2P(void)2212{2213EntityMenuParam *param = MenuParam_GetParam();22142215TimeAttackData_Clear();22162217param->puyoSelection = PUYO_SELECTION_VS_2P;2218strcpy(param->menuTag, "Extras");2219param->menuSelection = EXTRAS_SELECTION_PUYO;22202221RSDK.SetScene("Extras", "Puyo Puyo");2222RSDK.LoadScene();2223}22242225void MenuSetup_Extras_Puyo_vs2P_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_Puyo_vs2P, 32); }22262227void MenuSetup_Extras_Start_Credits(void)2228{2229EntityMenuParam *param = MenuParam_GetParam();22302231TimeAttackData_Clear();22322233param->bssSelection = CREDITS_SELECTION_EXTRAS;2234strcpy(param->menuTag, "Extras");2235param->menuSelection = EXTRAS_SELECTION_CREDITS;2236param->creditsReturnToMenu = true;22372238RSDK.SetScene("Presentation", "Credits");2239RSDK.LoadScene();2240}22412242void MenuSetup_Extras_Credits_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_Credits, 32); }22432244void MenuSetup_Extras_StartDAGarden(void)2245{2246EntityMenuParam *param = MenuParam_GetParam();22472248TimeAttackData_Clear();22492250strcpy(param->menuTag, "Extras");2251param->menuSelection = EXTRAS_SELECTION_DAGARDEN;22522253RSDK.SetScene("Extras", "D.A. Garden");2254RSDK.LoadScene();2255}22562257void MenuSetup_Extras_DAGarden_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_StartDAGarden, 32); }22582259void MenuSetup_Extras_Start_BSS_3K(void)2260{2261EntityMenuParam *param = MenuParam_GetParam();22622263TimeAttackData_Clear();22642265param->bssSelection = BSS_SELECTION_EXTRAS;2266strcpy(param->menuTag, "Extras");2267param->menuSelection = EXTRAS_SELECTION_BSS;22682269RSDK.SetScene("Blue Spheres", "Random");2270RSDK.LoadScene();2271}22722273void MenuSetup_Extras_BSS_3K_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_BSS_3K, 32); }22742275void MenuSetup_Extras_Start_BSS_Mania(void)2276{2277EntityMenuParam *param = MenuParam_GetParam();22782279TimeAttackData_Clear();22802281param->bssSelection = BSS_SELECTION_EXTRAS;2282strcpy(param->menuTag, "Extras");2283param->menuSelection = EXTRAS_SELECTION_BSS;22842285RSDK.SetScene("Blue Spheres", "Random 2");2286RSDK.LoadScene();2287}22882289void MenuSetup_Extras_BSS_Mania_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_BSS_Mania, 32); }22902291#endif22922293#if GAME_INCLUDE_EDITOR2294void MenuSetup_EditorDraw(void) {}22952296void MenuSetup_EditorLoad(void) {}2297#endif22982299void MenuSetup_Serialize(void) {}230023012302