Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Menu/MenuSetup.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: MenuSetup Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectMenuSetup *MenuSetup;
11
12
void MenuSetup_Update(void)
13
{
14
RSDK_THIS(MenuSetup);
15
16
StateMachine_Run(self->state);
17
18
#if !MANIA_USE_PLUS
19
if (self->state != MenuSetup_State_SetupLeaderboards) {
20
#endif
21
22
if (self->timer >= self->delay) {
23
StateMachine_Run(self->callback);
24
destroyEntity(self);
25
}
26
else {
27
self->timer++;
28
}
29
30
#if !MANIA_USE_PLUS
31
}
32
#endif
33
}
34
35
void MenuSetup_LateUpdate(void) {}
36
37
void MenuSetup_StaticUpdate(void)
38
{
39
#if MANIA_USE_PLUS
40
if (!MenuSetup->initializedAPI) {
41
MenuSetup->fxFade->speedOut = 0;
42
43
String tag;
44
INIT_STRING(tag);
45
RSDK.SetString(&tag, "Main Menu");
46
47
EntityUIControl *mainMenu = NULL; // this will crash if no entities have "Main Menu" as the tag, make sure one does!!!
48
foreach_all(UIControl, control)
49
{
50
if (RSDK.CompareStrings(&tag, &control->tag, false)) {
51
mainMenu = control;
52
foreach_break;
53
}
54
}
55
56
if (!ManiaModeMenu_InitAPI()) {
57
mainMenu->selectionDisabled = true;
58
return;
59
}
60
else {
61
mainMenu->selectionDisabled = false;
62
MenuSetup->initializedAPI = true;
63
64
String message;
65
Localization_GetString(&message, STR_RPC_MENU);
66
API_SetRichPresence(PRESENCE_MENU, &message);
67
}
68
}
69
70
if (!MenuSetup->initializedMenu) {
71
ManiaModeMenu_Initialize();
72
MenuSetup->initializedMenu = true;
73
}
74
75
if (!MenuSetup->initializedMenuReturn) {
76
ManiaModeMenu_HandleMenuReturn();
77
MenuSetup->initializedMenuReturn = true;
78
ManiaModeMenu_SetBGColors();
79
80
if (!globals->suppressAutoMusic)
81
ManiaModeMenu_ChangeMenuTrack();
82
83
globals->suppressAutoMusic = false;
84
}
85
86
MenuSetup->fxFade->speedOut = 12;
87
DialogRunner_GetUserAuthStatus();
88
#else
89
if (!MenuSetup->initializedAPI) {
90
String tag;
91
INIT_STRING(tag);
92
RSDK.SetString(&tag, "Main Menu");
93
94
EntityUIControl *mainMenu = NULL; // this will crash if no entities have "Main Menu" as the tag, make sure one does!!!
95
foreach_all(UIControl, control)
96
{
97
if (RSDK.CompareStrings(&tag, &control->tag, false)) {
98
mainMenu = control;
99
foreach_break;
100
}
101
}
102
103
if (!MenuSetup_InitAPI()) {
104
mainMenu->selectionDisabled = true;
105
return;
106
}
107
else {
108
mainMenu->selectionDisabled = false;
109
MenuSetup->initializedAPI = true;
110
111
String message;
112
Localization_GetString(&message, STR_RPC_MENU);
113
API_SetRichPresence(PRESENCE_MENU, &message);
114
}
115
}
116
117
if (!MenuSetup->initializedMenu) {
118
MenuSetup_Initialize();
119
MenuSetup->initializedMenu = true;
120
}
121
122
if (!MenuSetup->initializedMenuReturn) {
123
MenuSetup_HandleMenuReturn();
124
MenuSetup->initializedMenuReturn = true;
125
MenuSetup_SetBGColors();
126
127
if (!globals->suppressAutoMusic)
128
MenuSetup_ChangeMenuTrack();
129
130
globals->suppressAutoMusic = false;
131
}
132
133
APICallback_GetUserAuthStatus();
134
#endif
135
}
136
137
void MenuSetup_Draw(void)
138
{
139
RSDK_THIS(MenuSetup);
140
141
RSDK.FillScreen(self->fadeColor, self->fadeTimer, self->fadeTimer - 128, self->fadeTimer - 256);
142
}
143
144
void MenuSetup_Create(void *data)
145
{
146
RSDK_THIS(MenuSetup);
147
148
self->active = ACTIVE_ALWAYS;
149
self->visible = true;
150
self->drawGroup = 14;
151
}
152
153
void MenuSetup_StageLoad(void)
154
{
155
#if MANIA_USE_PLUS
156
EntityMenuParam *param = MenuParam_GetParam();
157
LogHelpers_Print("Menu recall ctrl: %s", param->menuTag);
158
159
MenuSetup->initializedMenuReturn = false;
160
MenuSetup->initializedMenu = false;
161
MenuSetup->initializedAPI = false;
162
MenuSetup->initializedSaves = false;
163
MenuSetup->fxFade = NULL;
164
165
if (!globals->suppressAutoMusic) {
166
Music_Stop();
167
Music->activeTrack = TRACK_NONE;
168
}
169
#else
170
Music_Stop();
171
Music->activeTrack = TRACK_NONE;
172
#endif
173
174
if (!SceneInfo->inEditor) {
175
switch (sku_platform) {
176
case PLATFORM_PC: LogHelpers_Print("PC SKU"); break;
177
case PLATFORM_PS4: LogHelpers_Print("PS4 SKU"); break;
178
case PLATFORM_XB1: LogHelpers_Print("XB1 SKU"); break;
179
case PLATFORM_SWITCH: LogHelpers_Print("NX SKU"); break;
180
case PLATFORM_DEV: LogHelpers_Print("DEV SKU"); break;
181
default: LogHelpers_Print("INVALID PLATFORM: %d", sku_platform); break;
182
}
183
184
switch (sku_region) {
185
case REGION_US: LogHelpers_Print("US REGION"); break;
186
case REGION_JP: LogHelpers_Print("JP REGION"); break;
187
case REGION_EU: LogHelpers_Print("EU REGION"); break;
188
default: LogHelpers_Print("INVALID REGION: %d", sku_region); break;
189
}
190
}
191
192
// Bug Details(?):
193
// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)
194
// but the memset size is only 1024 (sizeof(uint8) * 0x400)
195
// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal
196
memset(globals->noSaveSlot, 0, 0x400);
197
198
globals->continues = 0;
199
#if MANIA_USE_PLUS
200
globals->recallEntities = false;
201
#else
202
MenuSetup->vsTotalTimer = 120;
203
#endif
204
205
RSDK.SetVideoSetting(VIDEOSETTING_SCREENCOUNT, 1);
206
207
foreach_all(FXFade, fade) { MenuSetup->fxFade = fade; }
208
}
209
210
void MenuSetup_StartTransition(void (*callback)(void), int32 delay)
211
{
212
EntityMenuSetup *menuSetup = CREATE_ENTITY(MenuSetup, NULL, -0x100000, -0x100000);
213
214
menuSetup->active = ACTIVE_ALWAYS;
215
menuSetup->fadeColor = 0x000000;
216
menuSetup->fadeShift = 5;
217
menuSetup->delay = delay;
218
#if MANIA_USE_PLUS
219
menuSetup->state = ManiaModeMenu_State_HandleTransition;
220
#else
221
menuSetup->state = MenuSetup_State_HandleTransition;
222
#endif
223
menuSetup->callback = callback;
224
}
225
226
#if !MANIA_USE_PLUS
227
void MenuSetup_StartTransitionLB(void (*callback)(void), int32 delay)
228
{
229
EntityMenuSetup *menuSetup = CREATE_ENTITY(MenuSetup, NULL, -0x100000, -0x100000);
230
231
menuSetup->active = ACTIVE_ALWAYS;
232
menuSetup->fadeColor = 0x000000;
233
menuSetup->fadeShift = 5;
234
menuSetup->delay = delay;
235
menuSetup->state = MenuSetup_State_SetupLeaderboards;
236
menuSetup->callback = callback;
237
}
238
#endif
239
240
// START PRE-PLUS AREA
241
#if !MANIA_USE_PLUS
242
void MenuSetup_Initialize(void)
243
{
244
String tag;
245
INIT_STRING(tag);
246
247
foreach_all(UIControl, control)
248
{
249
RSDK.SetString(&tag, "Main Menu");
250
if (RSDK.CompareStrings(&tag, &control->tag, false)) {
251
MenuSetup->mainMenu = control;
252
control->backPressCB = MenuSetup_BackPressCB_ReturnToTitle;
253
}
254
255
RSDK.SetString(&tag, "Time Attack");
256
if (RSDK.CompareStrings(&tag, &control->tag, false))
257
MenuSetup->timeAttack = control;
258
259
RSDK.SetString(&tag, "Time Attack Zones");
260
if (RSDK.CompareStrings(&tag, &control->tag, false))
261
MenuSetup->timeAttackZones = control;
262
263
RSDK.SetString(&tag, "Leaderboards");
264
if (RSDK.CompareStrings(&tag, &control->tag, false)) {
265
MenuSetup->leaderboards = control;
266
control->backPressCB = MenuSetup_TA_Leaderboards_BackPressCB;
267
}
268
269
RSDK.SetString(&tag, "Competition");
270
if (RSDK.CompareStrings(&tag, &control->tag, false)) {
271
MenuSetup->competition = control;
272
control->backPressCB = MenuSetup_VS_BackoutFromVsCharSelect;
273
}
274
275
RSDK.SetString(&tag, "Competition Rules");
276
if (RSDK.CompareStrings(&tag, &control->tag, false))
277
MenuSetup->competitionRules = control;
278
279
RSDK.SetString(&tag, "Competition Zones");
280
if (RSDK.CompareStrings(&tag, &control->tag, false)) {
281
MenuSetup->competitionZones = control;
282
control->backPressCB = MenuSetup_VS_CompZones_BackPressCB;
283
}
284
285
RSDK.SetString(&tag, "Competition Round");
286
if (RSDK.CompareStrings(&tag, &control->tag, false))
287
MenuSetup->competitionRound = control;
288
289
RSDK.SetString(&tag, "Competition Total");
290
if (RSDK.CompareStrings(&tag, &control->tag, false))
291
MenuSetup->competitionTotal = control;
292
293
RSDK.SetString(&tag, "Save Select");
294
if (RSDK.CompareStrings(&tag, &control->tag, false))
295
MenuSetup->saveSelect = control;
296
297
RSDK.SetString(&tag, "No Save Mode");
298
if (RSDK.CompareStrings(&tag, &control->tag, false))
299
MenuSetup->noSaveMode = control;
300
301
RSDK.SetString(&tag, "Secrets");
302
if (RSDK.CompareStrings(&tag, &control->tag, false))
303
MenuSetup->secrets = control;
304
305
RSDK.SetString(&tag, "Extras");
306
if (RSDK.CompareStrings(&tag, &control->tag, false))
307
MenuSetup->extras = control;
308
309
RSDK.SetString(&tag, "Options");
310
if (RSDK.CompareStrings(&tag, &control->tag, false))
311
MenuSetup->options = control;
312
313
RSDK.SetString(&tag, "Language");
314
if (RSDK.CompareStrings(&tag, &control->tag, false))
315
MenuSetup->language = control;
316
317
RSDK.SetString(&tag, "Video");
318
if (RSDK.CompareStrings(&tag, &control->tag, false))
319
MenuSetup->video = control;
320
321
RSDK.SetString(&tag, "Video WIN");
322
if (RSDK.CompareStrings(&tag, &control->tag, false))
323
MenuSetup->video_win = control;
324
325
RSDK.SetString(&tag, "Sound");
326
if (RSDK.CompareStrings(&tag, &control->tag, false))
327
MenuSetup->sound = control;
328
329
RSDK.SetString(&tag, "Controls WIN");
330
if (RSDK.CompareStrings(&tag, &control->tag, false))
331
MenuSetup->controls_win = control;
332
333
RSDK.SetString(&tag, "Controls KB");
334
if (RSDK.CompareStrings(&tag, &control->tag, false))
335
MenuSetup->controls_KB = control;
336
337
RSDK.SetString(&tag, "Controls PS4");
338
if (RSDK.CompareStrings(&tag, &control->tag, false))
339
MenuSetup->controls_PS4 = control;
340
341
RSDK.SetString(&tag, "Controls XB1");
342
if (RSDK.CompareStrings(&tag, &control->tag, false))
343
MenuSetup->controls_XB1 = control;
344
345
RSDK.SetString(&tag, "Controls NX");
346
if (RSDK.CompareStrings(&tag, &control->tag, false))
347
MenuSetup->controls_NX = control;
348
349
RSDK.SetString(&tag, "Controls NX Grip");
350
if (RSDK.CompareStrings(&tag, &control->tag, false))
351
MenuSetup->controls_NX_Grip = control;
352
353
RSDK.SetString(&tag, "Controls NX Joycon");
354
if (RSDK.CompareStrings(&tag, &control->tag, false))
355
MenuSetup->controls_NX_JoyCon = control;
356
357
RSDK.SetString(&tag, "Controls NX Pro");
358
if (RSDK.CompareStrings(&tag, &control->tag, false))
359
MenuSetup->controls_NX_Pro = control;
360
}
361
362
foreach_all(UIButtonPrompt, prompt)
363
{
364
EntityUIControl *saveControl = MenuSetup->saveSelect;
365
EntityUIControl *leaderboardsControl = MenuSetup->leaderboards;
366
EntityUIControl *optionsControl = MenuSetup->options;
367
368
if (UIControl_ContainsPos(saveControl, &prompt->position) && prompt->buttonID == 2)
369
MenuSetup->delSavePrompt = prompt;
370
371
if (UIControl_ContainsPos(leaderboardsControl, &prompt->position) && prompt->buttonID == 3)
372
MenuSetup->leaderboardPrompt = prompt;
373
374
if (UIControl_ContainsPos(optionsControl, &prompt->position) && prompt->buttonID == 3)
375
MenuSetup->optionsPrompt = prompt;
376
}
377
378
foreach_all(UILeaderboard, leaderboard) { MenuSetup->leaderboardWidget = leaderboard; }
379
380
foreach_all(UIInfoLabel, label)
381
{
382
EntityUIControl *roundControl = MenuSetup->competitionRound;
383
EntityUIControl *totalControl = MenuSetup->competitionTotal;
384
385
if (UIControl_ContainsPos(roundControl, &label->position))
386
MenuSetup->roundLabel = label;
387
388
if (UIControl_ContainsPos(totalControl, &label->position))
389
MenuSetup->totalLabel = label;
390
}
391
392
foreach_all(UIVsScoreboard, scoreboard)
393
{
394
EntityUIControl *roundControl = MenuSetup->competitionRound;
395
EntityUIControl *totalControl = MenuSetup->competitionTotal;
396
397
if (UIControl_ContainsPos(roundControl, &scoreboard->position)) {
398
MenuSetup->roundScoreboard = scoreboard;
399
scoreboard->parentPos = &roundControl->position;
400
}
401
402
if (UIControl_ContainsPos(totalControl, &scoreboard->position)) {
403
MenuSetup->totalScoreboard = scoreboard;
404
scoreboard->parentPos = &totalControl->position;
405
}
406
}
407
408
MenuSetup_HandleUnlocks();
409
MenuSetup_SetupActions();
410
}
411
412
bool32 MenuSetup_InitAPI(void)
413
{
414
if (!MenuSetup->initializedAPI)
415
MenuSetup->fxFade->timer = 512;
416
417
APICallback_GetUserAuthStatus();
418
419
if (!APICallback->authStatus) {
420
APICallback_TryAuth();
421
}
422
else if (APICallback->authStatus != STATUS_CONTINUE) {
423
int32 storageStatus = APICallback_GetStorageStatus();
424
425
if (!storageStatus) {
426
APICallback_TryInitStorage();
427
}
428
else if (storageStatus != STATUS_CONTINUE) {
429
if (!API_GetNoSave() && (APICallback->authStatus != STATUS_OK || storageStatus != STATUS_OK)) {
430
if (APICallback->saveStatus != STATUS_CONTINUE) {
431
if (APICallback->saveStatus != STATUS_FORBIDDEN) {
432
APICallback_PromptSavePreference(storageStatus);
433
}
434
else {
435
RSDK.SetScene("Presentation", "Title Screen");
436
RSDK.LoadScene();
437
}
438
}
439
440
return false;
441
}
442
443
if (!MenuSetup->initializedSaves) {
444
UIWaitSpinner_StartWait();
445
Options_LoadFile(Options_LoadCallback);
446
SaveGame_LoadFile(SaveGame_SaveLoadedCB);
447
448
MenuSetup->initializedSaves = true;
449
}
450
451
if (MenuSetup->initializedAPI)
452
return true;
453
454
if (globals->optionsLoaded == STATUS_OK && globals->saveLoaded == STATUS_OK) {
455
456
if (!API_GetNoSave() && APICallback_NotifyAutosave())
457
return false;
458
459
UIWaitSpinner_FinishWait();
460
if (APICallback_CheckUnreadNotifs())
461
return false;
462
463
MenuSetup->initializedAPI = true;
464
return true;
465
}
466
467
if (API_GetNoSave()) {
468
UIWaitSpinner_FinishWait();
469
470
return true;
471
}
472
else {
473
if (globals->optionsLoaded == STATUS_ERROR || globals->saveLoaded == STATUS_ERROR) {
474
if (APICallback->saveStatus != STATUS_CONTINUE) {
475
if (APICallback->saveStatus == STATUS_FORBIDDEN) {
476
RSDK.SetScene("Presentation", "Title Screen");
477
RSDK.LoadScene();
478
}
479
else {
480
APICallback_PromptSavePreference(STATUS_CORRUPT);
481
}
482
}
483
}
484
}
485
}
486
}
487
488
return false;
489
}
490
491
void MenuSetup_SetupActions(void)
492
{
493
EntityUIControl *comp = MenuSetup->competition;
494
EntityUIControl *options = MenuSetup->options;
495
EntityUIControl *video = MenuSetup->video;
496
EntityUIControl *video_win = MenuSetup->video_win;
497
EntityUIControl *controls_win = MenuSetup->controls_win;
498
EntityUIControl *sound = MenuSetup->sound;
499
EntityUIControl *saveSel = MenuSetup->saveSelect;
500
EntityUIControl *secrets = MenuSetup->secrets;
501
EntityUIControl *extras = MenuSetup->extras;
502
EntityUIControl *compTotal = MenuSetup->competitionTotal;
503
EntityUIControl *compRound = MenuSetup->competitionRound;
504
EntityUIControl *compRules = MenuSetup->competitionRules;
505
EntityUIControl *language = MenuSetup->language;
506
507
foreach_all(UIModeButton, modeButton) { modeButton->actionCB = MenuSetup_MenuButton_ActionCB; }
508
foreach_all(UISaveSlot, saveSlot) { saveSlot->actionCB = MenuSetup_SaveSlot_ActionCB; }
509
510
foreach_all(UIButton, button)
511
{
512
switch (button->listID) {
513
case 17:
514
if (!button->frameID) {
515
if (GameInfo->platform == PLATFORM_PC || GameInfo->platform == PLATFORM_DEV) {
516
button->actionCB = MenuSetup_ExitGame_ActionCB;
517
}
518
else {
519
EntityUIControl *control = MenuSetup->mainMenu;
520
--control->buttonCount;
521
control->buttons[5] = NULL;
522
destroyEntity(button);
523
}
524
}
525
break;
526
527
case 1:
528
if (button->frameID == 4)
529
button->actionCB = MenuSetup_OpenExtrasMenu_ActionCB;
530
break;
531
532
case 7:
533
if (button->frameID == 4) {
534
button->actionCB = MenuSetup_Extras_DAGarden_ActionCB;
535
}
536
else if (button->frameID == 8) {
537
button->actionCB = MenuSetup_Extras_Credits_ActionCB;
538
button->clearParentState = true;
539
}
540
break;
541
}
542
543
if (UIControl_ContainsPos(controls_win, &button->position))
544
button->actionCB = MenuSetup_Options_OpenKBControlsMenu;
545
546
if (UIControl_ContainsPos(compRules, &button->position) && button->listID == 9 && button->frameID == 2)
547
button->actionCB = MenuSetup_VS_RulesButton_ActionCB;
548
549
if (UIControl_ContainsPos(secrets, &button->position) && button->listID == 9 && button->frameID == 2)
550
button->actionCB = MenuSetup_OpenSaveSelectMenu;
551
552
if (UIControl_ContainsPos(options, &button->position) && button->listID == 3) {
553
switch (button->frameID) {
554
case 0: button->actionCB = MenuSetup_Options_VideoMenuButton_ActionCB; break;
555
case 1: button->actionCB = MenuSetup_Options_SoundMenuButton_ActionCB; break;
556
case 2: button->actionCB = MenuSetup_Options_ControlsMenuButton_ActionCB; break;
557
case 3: button->actionCB = MenuSetup_Options_LanguageMenuButton_ActionCB; break;
558
}
559
}
560
561
if (UIControl_ContainsPos(language, &button->position))
562
button->actionCB = MenuSetup_OptionsLanguage_LanguageButton_ActionCB;
563
564
if (UIControl_ContainsPos(video, &button->position) && button->listID == 3 && button->frameID == 0)
565
button->choiceChangeCB = MenuSetup_OptionsVideo_ShaderButton_ActionCB;
566
567
if (UIControl_ContainsPos(video_win, &button->position) && button->listID == 17) {
568
switch (button->frameID) {
569
case 2: button->choiceChangeCB = MenuSetup_OptionsVideo_ShaderButton_ActionCB; break;
570
case 7: button->choiceChangeCB = MenuSetup_OptionsVideo_WindowScaleButton_ActionCB; break;
571
case 13: button->choiceChangeCB = MenuSetup_OptionsVideo_BorderlessButton_ActionCB; break;
572
case 14: button->choiceChangeCB = MenuSetup_OptionsVideo_FullscreenButton_ActionCB; break;
573
case 15: button->choiceChangeCB = MenuSetup_OptionsVideo_VSyncButton_ActionCB; break;
574
case 16: button->choiceChangeCB = MenuSetup_OptionsVideo_TripleBufferButton_ActionCB; break;
575
default: break;
576
}
577
}
578
}
579
580
foreach_all(UIChoice, choice)
581
{
582
if (choice->listID == 7) {
583
switch (choice->frameID) {
584
case 2:
585
choice->actionCB = MenuSetup_Extras_Puyo_vsAI_ActionCB;
586
choice->textVisible = true;
587
break;
588
589
case 3:
590
choice->actionCB = MenuSetup_Extras_Puyo_vs2P_ActionCB;
591
choice->textVisible = true;
592
break;
593
594
case 6:
595
choice->actionCB = MenuSetup_Extras_BSS_3K_ActionCB;
596
choice->textVisible = true;
597
break;
598
599
case 7:
600
choice->actionCB = MenuSetup_Extras_BSS_Mania_ActionCB;
601
choice->textVisible = true;
602
break;
603
604
default: break;
605
}
606
}
607
}
608
609
foreach_all(UICharButton, charButton)
610
{
611
if (charButton->parent == (Entity *)MenuSetup->timeAttack) {
612
switch (charButton->characterID) {
613
case 0: charButton->actionCB = MenuSetup_TA_OpenZoneList_Sonic; break;
614
case 1: charButton->actionCB = MenuSetup_TA_OpenZoneList_Tails; break;
615
case 2: charButton->actionCB = MenuSetup_TA_OpenZoneList_Knux; break;
616
}
617
}
618
}
619
620
foreach_all(UITAZoneModule, module) { module->actionCB = MenuSetup_TA_TAZoneModule_ActionCB; }
621
622
MenuSetup->leaderboardWidget->yPressCB = MenuSetup_TA_Leaderboards_YPressCB;
623
624
foreach_all(UISlider, slider)
625
{
626
if (UIControl_ContainsPos(sound, &slider->position) && slider->listID == 5)
627
slider->sliderChangedCB = MenuSetup_OptionsVideo_UISlider_ChangedCB;
628
}
629
630
comp->processButtonInputCB = MenuSetup_VS_ProcessButtonCB;
631
comp->menuSetupCB = MenuSetup_VS_MenuSetupCB;
632
633
if (comp->active == ACTIVE_ALWAYS) {
634
RSDK_THIS(UIControl);
635
self->childHasFocus = false;
636
637
foreach_all(UIVsCharSelector, selector)
638
{
639
selector->isSelected = true;
640
selector->ready = false;
641
selector->processButtonCB = UIVsCharSelector_ProcessButtonCB;
642
}
643
}
644
645
compRound->processButtonInputCB = MenuSetup_VS_Round_ProcessButtonCB;
646
compRound->menuSetupCB = MenuSetup_VS_Round_MenuSetupCB;
647
if (compRound->active == ACTIVE_ALWAYS)
648
MenuSetup_VS_Round_MenuSetupCB();
649
650
compTotal->processButtonInputCB = MenuSetup_VS_Total_ProcessButtonCB;
651
compTotal->menuSetupCB = MenuSetup_VS_Total_MenuSetupCB;
652
compTotal->menuUpdateCB = MenuSetup_VS_Total_MenuUpdateCB;
653
compTotal->targetPos.y = compTotal->startPos.y;
654
compTotal->position.y = compTotal->startPos.y;
655
if (compTotal->active == ACTIVE_ALWAYS)
656
MenuSetup_VS_Total_MenuSetupCB();
657
658
saveSel->menuUpdateCB = MenuSetup_SaveSel_MenuUpdateCB;
659
saveSel->yPressCB = MenuSetup_SaveSel_YPressCB;
660
661
extras->processButtonInputCB = MenuSetup_Extras_ProcessButtonCB;
662
663
options->menuSetupCB = MenuSetup_Options_MenuSetupCB;
664
if (sku_platform == PLATFORM_DEV || sku_platform == PLATFORM_SWITCH)
665
options->yPressCB = MenuSetup_Options_LaunchManual;
666
else
667
MenuSetup->optionsPrompt->visible = false;
668
669
video_win->menuUpdateCB = MenuSetup_OptionsVideo_Win_MenuUpdateCB;
670
671
foreach_all(UIVsZoneButton, zoneButton) { zoneButton->actionCB = MenuSetup_VS_StartMatch_ActionCB; }
672
}
673
674
void MenuSetup_HandleUnlocks(void)
675
{
676
EntityUIControl *mainMenu = MenuSetup->mainMenu;
677
678
EntityUIButton *taButton = mainMenu->buttons[1];
679
taButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_TIMEATTACK);
680
681
EntityUIButton *vsButton = mainMenu->buttons[2];
682
vsButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_COMPETITION);
683
684
foreach_all(UITAZoneModule, module) { module->disabled = !GameProgress_GetZoneUnlocked(module->zoneID); }
685
686
int32 maxRounds = 0;
687
foreach_all(UIVsZoneButton, zoneButton)
688
{
689
zoneButton->xOut = !GameProgress_GetZoneUnlocked(zoneButton->zoneID);
690
zoneButton->obfuscate = zoneButton->xOut;
691
if (!zoneButton->xOut)
692
++maxRounds;
693
}
694
695
EntityUIButton *matchLength = MenuSetup->competitionRules->buttons[1];
696
if (matchLength->choiceCount >= 1) {
697
EntityUIVsRoundPicker *vsRoundPicker = (EntityUIVsRoundPicker *)UIButton_GetChoicePtr(matchLength, matchLength->selection);
698
699
if (vsRoundPicker->classID == UIVsRoundPicker->classID) {
700
vsRoundPicker->maxVal = maxRounds;
701
vsRoundPicker->val = MIN(vsRoundPicker->val, maxRounds);
702
}
703
}
704
705
EntityUIControl *secrets = MenuSetup->secrets;
706
EntityUIButton *debugMode = secrets->buttons[0];
707
debugMode->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_DEBUGMODE);
708
if (debugMode->disabled)
709
UIButton_ManageChoices(debugMode);
710
711
EntityUIButton *sonicAbility = secrets->buttons[1];
712
EntityUIButton *peeloutChoice = UIButton_GetChoicePtr(sonicAbility, 1);
713
EntityUIButton *instaShieldChoice = UIButton_GetChoicePtr(sonicAbility, 2);
714
715
sonicAbility->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_PEELOUT);
716
if (sonicAbility->disabled)
717
UIButton_ManageChoices(sonicAbility);
718
719
peeloutChoice->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_PEELOUT);
720
instaShieldChoice->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_INSTASHIELD);
721
722
EntityUIButton *andKnux = secrets->buttons[2];
723
andKnux->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_ANDKNUX);
724
if (andKnux->disabled)
725
UIButton_ManageChoices(andKnux);
726
727
EntityUIControl *extras = MenuSetup->extras;
728
729
EntityUIButton *bssButton = extras->buttons[0];
730
bssButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_BLUESPHERES);
731
if (bssButton->disabled)
732
UIButton_ManageChoices(bssButton);
733
734
EntityUIButton *puyoButton = extras->buttons[1];
735
puyoButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_MEANBEAN);
736
if (puyoButton->disabled)
737
UIButton_ManageChoices(puyoButton);
738
739
EntityUIButton *daGardenButton = extras->buttons[2];
740
daGardenButton->disabled = !GameProgress_CheckUnlock(GAMEPROGRESS_UNLOCK_DAGARDEN) && !globals->medallionDebug;
741
}
742
743
void MenuSetup_HandleMenuReturn(void)
744
{
745
EntityMenuParam *param = MenuParam_GetParam();
746
747
char buffer[0x100];
748
memset(buffer, 0, 0x100);
749
if (strcmp(param->menuTag, "") == 0)
750
UIUsernamePopup_ShowPopup();
751
752
if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV)
753
MenuSetup_OptionsVideo_Win_MenuUpdateCB();
754
755
foreach_all(UIControl, control)
756
{
757
if (strcmp(param->menuTag, "") != 0) {
758
RSDK.GetCString(buffer, &control->tag);
759
760
if (strcmp((const char *)buffer, param->menuTag) != 0) {
761
UIControl_SetInactiveMenu(control);
762
}
763
else {
764
UIControl_SetActiveMenu(control);
765
control->buttonID = param->menuSelection;
766
767
if (control == MenuSetup->timeAttackZones && param->startedTAAttempt)
768
UITAZoneModule_SetStartupModule(control, param->characterID, param->zoneID, param->actID, param->timeScore);
769
}
770
}
771
772
if (control == MenuSetup->timeAttack && param->startedTAAttempt) {
773
int32 charID = param->characterID - 1;
774
control->buttonID = charID;
775
control->buttons[charID]->isSelected = true;
776
}
777
778
if (control == MenuSetup->extras && param->puyoSelection == PUYO_SELECTION_VS_2P) {
779
UIButton_SetChoiceSelection(control->buttons[1], 1);
780
}
781
782
if (control == MenuSetup->secrets) {
783
EntityUIControl *control = MenuSetup->secrets;
784
785
UIButton_SetChoiceSelection(control->buttons[0], (globals->medalMods & MEDAL_ANDKNUCKLES) != 0);
786
787
int32 medals = globals->medalMods;
788
if (medals & MEDAL_NODROPDASH) {
789
if (medals & MEDAL_PEELOUT)
790
UIButton_SetChoiceSelection(control->buttons[1], 1);
791
else if (medals & MEDAL_INSTASHIELD)
792
UIButton_SetChoiceSelection(control->buttons[1], 2);
793
}
794
else
795
UIButton_SetChoiceSelection(control->buttons[1], 0);
796
797
UIButton_SetChoiceSelection(control->buttons[2], (globals->medalMods & MEDAL_ANDKNUCKLES) != 0);
798
}
799
800
if (control == MenuSetup->video) {
801
EntityUIControl *control = MenuSetup->video;
802
EntityUIButton *button = control->buttons[0];
803
UIButton_SetChoiceSelection(button, RSDK.GetVideoSetting(VIDEOSETTING_SHADERID));
804
}
805
806
if (control == MenuSetup->sound) {
807
EntityUIControl *control = MenuSetup->sound;
808
809
EntityUISlider *slider = (EntityUISlider *)control->buttons[0];
810
slider->sliderPos = RSDK.GetVideoSetting(VIDEOSETTING_STREAM_VOL);
811
812
slider = (EntityUISlider *)control->buttons[1];
813
slider->sliderPos = RSDK.GetVideoSetting(VIDEOSETTING_SFX_VOL);
814
}
815
816
if (control == MenuSetup->language) {
817
EntityUIControl *control = MenuSetup->language;
818
819
control->startingID = Localization->language;
820
control->buttonID = Localization->language;
821
}
822
823
EntityCompetitionSession *session = CompetitionSession_GetSession();
824
if (session->inMatch) {
825
if (control == MenuSetup->competition) {
826
foreach_all(UIVsCharSelector, selector)
827
{
828
selector->prevFrameID = -1;
829
switch (session->playerID[selector->playerID]) {
830
case ID_SONIC: selector->frameID = 0; break;
831
case ID_TAILS: selector->frameID = 1; break;
832
case ID_KNUCKLES: selector->frameID = 2; break;
833
default: break;
834
}
835
}
836
}
837
838
if (control == MenuSetup->competitionRules) {
839
switch (session->itemMode) {
840
case ITEMS_FIXED: UIButton_SetChoiceSelection(control->buttons[0], 0); break;
841
case ITEMS_RANDOM: UIButton_SetChoiceSelection(control->buttons[0], 2); break;
842
case ITEMS_TELEPORT: UIButton_SetChoiceSelection(control->buttons[0], 1); break;
843
}
844
845
EntityUIVsRoundPicker *vsRoundPicker =
846
(EntityUIVsRoundPicker *)UIButton_GetChoicePtr(control->buttons[1], control->buttons[1]->selection);
847
if (vsRoundPicker)
848
vsRoundPicker->val = session->matchCount;
849
}
850
851
if (control == MenuSetup->competitionZones) {
852
for (int32 i = 0; i < COMPETITION_STAGE_COUNT; ++i) {
853
EntityUIVsZoneButton *button = (EntityUIVsZoneButton *)control->buttons[i];
854
if (button && session->completedStages[i])
855
button->xOut = true;
856
}
857
}
858
}
859
}
860
861
TimeAttackData_Clear();
862
}
863
864
// Main Menu
865
int32 MenuSetup_GetActiveMenu(void)
866
{
867
EntityUIControl *control = UIControl_GetUIControl();
868
869
if (control == MenuSetup->mainMenu || control == MenuSetup->extras || control == MenuSetup->options || control == MenuSetup->video
870
|| control == MenuSetup->sound || control == MenuSetup->controls_win || control == MenuSetup->controls_KB
871
|| control == MenuSetup->controls_PS4 || control == MenuSetup->controls_XB1 || control == MenuSetup->controls_NX
872
|| control == MenuSetup->controls_NX_Grip || control == MenuSetup->controls_NX_JoyCon || control == MenuSetup->controls_NX_Pro) {
873
return MAINMENU_MAIN;
874
}
875
876
if (control == MenuSetup->timeAttack || control == MenuSetup->timeAttackZones || control == MenuSetup->leaderboards
877
|| control == MenuSetup->competition || control == MenuSetup->competitionRules || control == MenuSetup->competitionZones) {
878
return MAINMENU_TIMEATTACK;
879
}
880
881
if (control == MenuSetup->competitionRound || control == MenuSetup->competitionTotal)
882
return MAINMENU_COMPETITION;
883
884
if (control == MenuSetup->saveSelect || control == MenuSetup->noSaveMode || control == MenuSetup->secrets)
885
return MAINMENU_SAVESELECT;
886
887
return MAINMENU_MAIN;
888
}
889
890
void MenuSetup_ChangeMenuTrack(void)
891
{
892
int32 trackID = 0;
893
switch (MenuSetup_GetActiveMenu()) {
894
default:
895
case MAINMENU_MAIN: trackID = 0; break;
896
case MAINMENU_TIMEATTACK: trackID = 1; break;
897
case MAINMENU_COMPETITION: trackID = 2; break;
898
case MAINMENU_SAVESELECT: trackID = 3; break;
899
}
900
901
if (!Music_IsPlaying())
902
Music_PlayTrack(trackID);
903
else if (Music->activeTrack != trackID)
904
Music_TransitionTrack(trackID, 0.12);
905
}
906
907
void MenuSetup_SetBGColors(void)
908
{
909
switch (MenuSetup_GetActiveMenu()) {
910
case MAINMENU_MAIN: UIBackground->activeColors = UIBackground->bgColors; break;
911
912
case MAINMENU_TIMEATTACK:
913
case MAINMENU_COMPETITION: UIBackground->activeColors = &UIBackground->bgColors[3]; break;
914
915
case MAINMENU_SAVESELECT: UIBackground->activeColors = &UIBackground->bgColors[6]; break;
916
917
default: break;
918
}
919
}
920
921
void MenuSetup_MenuButton_ActionCB(void)
922
{
923
RSDK_THIS(UIModeButton);
924
925
switch (self->buttonID) {
926
case 0: // Mania Mode
927
if (API_GetNoSave()) {
928
UIControl_MatchMenuTag("No Save Mode");
929
}
930
else {
931
MenuSetup->saveSelect->buttonID = 7;
932
UIControl_MatchMenuTag("Save Select");
933
}
934
break;
935
936
case 1: // Time Attack
937
UIControl_MatchMenuTag("Time Attack");
938
break;
939
940
case 2: // Competition
941
UIControl_MatchMenuTag("Competition");
942
break;
943
944
case 3: // Options
945
UIControl_MatchMenuTag("Options");
946
break;
947
948
default: return;
949
}
950
}
951
952
bool32 MenuSetup_BackPressCB_ReturnToTitle(void)
953
{
954
MenuSetup_StartReturnToTitle();
955
956
return true;
957
}
958
959
void MenuSetup_StartReturnToTitle(void)
960
{
961
EntityUIControl *control = UIControl_GetUIControl();
962
if (control)
963
control->state = StateMachine_None;
964
965
Music_FadeOut(0.05);
966
MenuSetup_StartTransition(MenuSetup_ReturnToTitle, 32);
967
}
968
969
void MenuSetup_ReturnToTitle(void)
970
{
971
TimeAttackData_Clear();
972
973
RSDK.SetScene("Presentation", "Title Screen");
974
RSDK.LoadScene();
975
}
976
977
void MenuSetup_ExitGame(void) { APICallback_ExitGame(); }
978
979
void MenuSetup_ExitGame_ActionCB(void)
980
{
981
String string;
982
INIT_STRING(string);
983
984
#if GAME_VERSION != VER_100
985
Localization_GetString(&string, STR_QUITWARNING);
986
#else
987
Localization_GetString(&string, STR_QUITWARNINGLOSEPROGRESS);
988
#endif
989
UIDialog_CreateDialogYesNo(&string, MenuSetup_ExitGame_CB, NULL, true, true);
990
}
991
992
void MenuSetup_ExitGame_CB(void)
993
{
994
if (UIControl_GetUIControl())
995
UIControl_GetUIControl()->state = StateMachine_None;
996
997
Music_FadeOut(0.02);
998
MenuSetup_StartTransition(MenuSetup_ExitGame, 64);
999
}
1000
1001
void MenuSetup_State_HandleTransition(void)
1002
{
1003
RSDK_THIS(MenuSetup);
1004
1005
self->fadeTimer = CLAMP(self->timer << ((self->fadeShift & 0xFF) - 1), 0, 512);
1006
}
1007
1008
// Save Select
1009
int32 MenuSetup_GetMedalMods(void)
1010
{
1011
EntityUIControl *control = MenuSetup->secrets;
1012
1013
int32 mods = 0;
1014
if (control->buttons[0]->selection == 1)
1015
mods |= MEDAL_DEBUGMODE;
1016
1017
if (control->buttons[1]->selection == 1) {
1018
mods |= MEDAL_NODROPDASH;
1019
mods |= MEDAL_PEELOUT;
1020
}
1021
else if (control->buttons[1]->selection == 2) {
1022
mods |= MEDAL_NODROPDASH;
1023
mods |= MEDAL_INSTASHIELD;
1024
}
1025
1026
if (control->buttons[2]->selection == 1)
1027
mods |= MEDAL_ANDKNUCKLES;
1028
1029
return mods;
1030
}
1031
1032
void MenuSetup_OpenSaveSelectMenu(void)
1033
{
1034
EntityUIControl *control = MenuSetup->saveSelect;
1035
1036
UIControl_MatchMenuTag("Save Select");
1037
control->childHasFocus = false;
1038
}
1039
1040
void MenuSetup_SaveFileCB(void)
1041
{
1042
UIWaitSpinner_FinishWait();
1043
RSDK.LoadScene();
1044
}
1045
1046
void MenuSetup_SaveSlot_ActionCB(void)
1047
{
1048
RSDK_THIS(UISaveSlot);
1049
1050
SaveRAM *saveRAM = (SaveRAM *)SaveGame_GetDataPtr(self->slotID);
1051
1052
bool32 loadingSave = false;
1053
if (self->type) {
1054
// Bug Details(?):
1055
// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)
1056
// but the memset size is only 1024 (sizeof(uint8) * 0x400)
1057
// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal
1058
memset(globals->noSaveSlot, 0, 0x400);
1059
1060
globals->tempFlags = 0;
1061
globals->saveSlotID = NO_SAVE_SLOT;
1062
globals->gameMode = MODE_NOSAVE;
1063
globals->medalMods = MenuSetup_GetMedalMods();
1064
}
1065
else {
1066
globals->saveSlotID = self->slotID;
1067
globals->medalMods = 0;
1068
globals->gameMode = MODE_MANIA;
1069
1070
if (self->isNewSave) {
1071
int32 *saveData = SaveGame_GetDataPtr(self->slotID % 8);
1072
1073
// Bug Details(?):
1074
// see above
1075
memset(saveData, 0, 0x400);
1076
1077
saveRAM->saveState = 1;
1078
saveRAM->characterID = self->frameID;
1079
saveRAM->zoneID = 0;
1080
saveRAM->lives = 3;
1081
saveRAM->collectedEmeralds = self->saveEmeralds;
1082
saveRAM->continues = 0;
1083
1084
UIWaitSpinner_StartWait();
1085
loadingSave = true;
1086
SaveGame_SaveFile(MenuSetup_SaveFileCB);
1087
}
1088
else {
1089
if (saveRAM->saveState == SAVEGAME_COMPLETE) {
1090
SaveGame_ClearCollectedSpecialRings();
1091
saveRAM->score = 0;
1092
saveRAM->score1UP = 500000;
1093
}
1094
1095
loadingSave = true;
1096
SaveGame_SaveFile(MenuSetup_SaveFileCB);
1097
}
1098
}
1099
1100
switch (self->frameID) {
1101
case 0: // Sonic & Tails
1102
case 1: globals->playerID = ID_SONIC; break;
1103
1104
case 2: globals->playerID = ID_TAILS; break;
1105
1106
case 3: globals->playerID = ID_KNUCKLES; break;
1107
1108
default: break;
1109
}
1110
1111
if ((globals->medalMods & MEDAL_ANDKNUCKLES))
1112
globals->playerID |= ID_KNUCKLES_ASSIST;
1113
else if (!self->frameID)
1114
globals->playerID |= ID_TAILS_ASSIST;
1115
1116
if (self->type == UISAVESLOT_NOSAVE || self->isNewSave) {
1117
if (((globals->medalMods & MEDAL_DEBUGMODE) && (ControllerInfo->keyC.down || ControllerInfo->keyX.down))
1118
&& self->type == UISAVESLOT_NOSAVE)
1119
RSDK.SetScene("Presentation", "Level Select");
1120
else
1121
RSDK.SetScene("Cutscenes", "Angel Island Zone");
1122
}
1123
else {
1124
RSDK.SetScene("Mania Mode", "");
1125
SceneInfo->listPos += TimeAttackData_GetManiaListPos(self->saveZoneID, ACT_1, self->frameID);
1126
}
1127
1128
if (!loadingSave) {
1129
globals->initCoolBonus = false;
1130
RSDK.LoadScene();
1131
}
1132
}
1133
1134
void MenuSetup_SaveSel_MenuUpdateCB(void)
1135
{
1136
EntityUIControl *control = MenuSetup->saveSelect;
1137
1138
if (control->active == ACTIVE_ALWAYS) {
1139
EntityUIButtonPrompt *prompt = MenuSetup->delSavePrompt;
1140
1141
// buttonID == 8: No Save Slot Button
1142
if (control->lastButtonID == 8) {
1143
prompt->promptID = 6;
1144
prompt->buttonID = 3;
1145
}
1146
else {
1147
prompt->promptID = 3;
1148
prompt->buttonID = 2;
1149
}
1150
}
1151
}
1152
1153
void MenuSetup_OpenSecretsMenu(void)
1154
{
1155
EntityUIControl *control = MenuSetup->secrets;
1156
control->childHasFocus = false;
1157
1158
UIControl_MatchMenuTag("Secrets");
1159
}
1160
1161
void MenuSetup_SaveSel_YPressCB(void)
1162
{
1163
EntityUIControl *control = MenuSetup->saveSelect;
1164
1165
// buttonID == 8: No Save Slot Button
1166
if (control->active == ACTIVE_ALWAYS && control->buttonID == 8) {
1167
RSDK.PlaySfx(UIWidgets->sfxAccept, false, 0xFF);
1168
UIControl->inputLocked = true;
1169
1170
UITransition_StartTransition(MenuSetup_OpenSecretsMenu, 0);
1171
}
1172
}
1173
1174
void MenuSetup_TA_OpenZoneList_Sonic(void)
1175
{
1176
EntityMenuParam *param = MenuParam_GetParam();
1177
TimeAttackData_Clear();
1178
1179
param->characterID = 1;
1180
1181
EntityUIControl *control = MenuSetup->timeAttackZones;
1182
for (int32 i = 0; i < control->buttonCount; ++i) {
1183
EntityUITAZoneModule *button = (EntityUITAZoneModule *)control->buttons[i];
1184
button->characterID = param->characterID;
1185
}
1186
1187
UIControl_MatchMenuTag("Time Attack Zones");
1188
}
1189
1190
void MenuSetup_TA_OpenZoneList_Tails(void)
1191
{
1192
EntityMenuParam *param = MenuParam_GetParam();
1193
TimeAttackData_Clear();
1194
1195
param->characterID = 2;
1196
1197
EntityUIControl *control = MenuSetup->timeAttackZones;
1198
for (int32 i = 0; i < control->buttonCount; ++i) {
1199
EntityUITAZoneModule *button = (EntityUITAZoneModule *)control->buttons[i];
1200
button->characterID = param->characterID;
1201
}
1202
1203
UIControl_MatchMenuTag("Time Attack Zones");
1204
}
1205
1206
void MenuSetup_TA_OpenZoneList_Knux(void)
1207
{
1208
EntityMenuParam *param = MenuParam_GetParam();
1209
TimeAttackData_Clear();
1210
1211
param->characterID = 3;
1212
1213
EntityUIControl *control = MenuSetup->timeAttackZones;
1214
for (int32 i = 0; i < control->buttonCount; ++i) {
1215
EntityUITAZoneModule *button = (EntityUITAZoneModule *)control->buttons[i];
1216
button->characterID = param->characterID;
1217
}
1218
1219
UIControl_MatchMenuTag("Time Attack Zones");
1220
}
1221
1222
void MenuSetup_TA_TAZoneModule_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_TA_StartAttempt, 32); }
1223
1224
void MenuSetup_TA_StartAttempt(void)
1225
{
1226
EntityMenuParam *param = MenuParam_GetParam();
1227
1228
sprintf(param->menuTag, "Time Attack Zones");
1229
param->menuSelection = param->zoneID;
1230
param->startedTAAttempt = true;
1231
1232
SaveGame_ResetPlayerState();
1233
1234
// Bug Details(?):
1235
// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)
1236
// but the memset size is only 1024 (sizeof(uint8) * 0x400)
1237
// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal
1238
memset(globals->noSaveSlot, 0, 0x400);
1239
1240
globals->continues = 0;
1241
globals->saveSlotID = NO_SAVE_SLOT;
1242
globals->gameMode = MODE_TIMEATTACK;
1243
globals->medalMods = 0;
1244
1245
RSDK.SetScene("Mania Mode", "");
1246
SceneInfo->listPos += TimeAttackData_GetManiaListPos(param->zoneID, param->actID, param->characterID);
1247
1248
switch (param->characterID) {
1249
case 1: globals->playerID = ID_SONIC; break;
1250
case 2: globals->playerID = ID_TAILS; break;
1251
case 3: globals->playerID = ID_KNUCKLES; break;
1252
default: break;
1253
}
1254
1255
RSDK.LoadScene();
1256
}
1257
1258
void MenuSetup_TA_Leaderboards_TransitionCB(void)
1259
{
1260
EntityUIControl *leaderboardControl = MenuSetup->leaderboards;
1261
EntityUILeaderboard *leaderboards = MenuSetup->leaderboardWidget;
1262
1263
UIControl->forceBackPress = false;
1264
leaderboardControl->active = ACTIVE_NEVER;
1265
leaderboardControl->visible = false;
1266
leaderboardControl->state = StateMachine_None;
1267
1268
UIControl_SetActiveMenu(MenuSetup->timeAttackZones);
1269
UITAZoneModule_SetStartupModule(MenuSetup->timeAttackZones, leaderboards->characterID, leaderboards->zoneID, leaderboards->actID, 0);
1270
}
1271
1272
bool32 MenuSetup_TA_Leaderboards_BackPressCB(void)
1273
{
1274
UITransition_StartTransition(MenuSetup_TA_Leaderboards_TransitionCB, 0);
1275
1276
return true;
1277
}
1278
1279
void MenuSetup_TA_Leaderboards_YPressCB(void)
1280
{
1281
EntityUILeaderboard *leaderboards = MenuSetup->leaderboardWidget;
1282
1283
UITAZoneModule_ShowLeaderboards(leaderboards->characterID, leaderboards->zoneID, leaderboards->actID, leaderboards->viewingUserRank, NULL);
1284
}
1285
1286
void MenuSetup_State_SetupLeaderboards(void)
1287
{
1288
RSDK_THIS(MenuSetup);
1289
1290
EntityUIDialog *dialog = MenuSetup->connectingDlg;
1291
EntityUILeaderboard *leaderboard = MenuSetup->leaderboardWidget;
1292
EntityUIButtonPrompt *prompt = MenuSetup->leaderboardPrompt;
1293
1294
int32 status = APICallback_LeaderboardStatus();
1295
1296
if (status == STATUS_CONTINUE) {
1297
String message;
1298
INIT_STRING(message);
1299
RSDK.InitString(&message, "", 0);
1300
1301
Localization_GetString(&message, STR_CONNECTING);
1302
UIDialog_SetupText(dialog, &message);
1303
}
1304
else if (status >= STATUS_ERROR) {
1305
status = APICallback_LeaderboardStatus();
1306
1307
int32 strID = status == STATUS_TIMEOUT ? STR_COMMERROR : STR_NOWIFI;
1308
1309
String message;
1310
INIT_STRING(message);
1311
RSDK.InitString(&message, "", 0);
1312
Localization_GetString(&message, strID);
1313
1314
UIDialog_SetupText(dialog, &message);
1315
UIDialog_AddButton(DIALOG_OK, dialog, NULL, true);
1316
1317
EntityUIControl *parent = dialog->parent;
1318
parent->rowCount = 1;
1319
parent->columnCount = 1;
1320
parent->buttonID = 0;
1321
1322
if (leaderboard->taRecord)
1323
leaderboard->viewingUserRank = !leaderboard->viewingUserRank;
1324
1325
prompt->promptID = leaderboard->viewingUserRank ? 14 : 15;
1326
prompt->prevPrompt = -1;
1327
prompt->visible = leaderboard->taRecord != 0;
1328
1329
self->callback = StateMachine_None;
1330
MenuSetup->connectingDlg = NULL;
1331
destroyEntity(self);
1332
}
1333
else if (status == STATUS_OK) {
1334
prompt->promptID = leaderboard->viewingUserRank ? 14 : 15;
1335
prompt->prevPrompt = -1;
1336
prompt->visible = leaderboard->taRecord != 0;
1337
1338
UILeaderboard_InitLeaderboard(leaderboard);
1339
UIDialog_CloseOnSel_HandleSelection(dialog, self->callback);
1340
1341
self->callback = StateMachine_None;
1342
MenuSetup->connectingDlg = NULL;
1343
destroyEntity(self);
1344
}
1345
}
1346
1347
// Competition
1348
void MenuSetup_VS_OpenCompRules(void) { UIControl_MatchMenuTag("Competition Rules"); }
1349
void MenuSetup_VS_OpenCompZones(void) { UIControl_MatchMenuTag("Competition Zones"); }
1350
1351
void MenuSetup_VS_ProcessButtonCB(void)
1352
{
1353
EntityUIControl *control = MenuSetup->competition;
1354
1355
if (control) {
1356
bool32 allPlayersReady = true;
1357
1358
foreach_all(UIVsCharSelector, charSel)
1359
{
1360
Entity *entStore = SceneInfo->entity;
1361
SceneInfo->entity = (Entity *)charSel;
1362
StateMachine_Run(charSel->processButtonCB);
1363
SceneInfo->entity = entStore;
1364
1365
if (allPlayersReady)
1366
allPlayersReady = charSel->ready ? !charSel->isSelected : false;
1367
}
1368
1369
if (allPlayersReady) {
1370
control->selectionDisabled = true;
1371
UITransition_StartTransition(MenuSetup_VS_OpenCompRules, 0);
1372
}
1373
}
1374
}
1375
1376
void MenuSetup_VS_MenuSetupCB(void)
1377
{
1378
RSDK_THIS(UIControl);
1379
1380
self->childHasFocus = false;
1381
1382
foreach_all(UIVsCharSelector, charSel)
1383
{
1384
charSel->isSelected = true;
1385
charSel->ready = false;
1386
charSel->processButtonCB = UIVsCharSelector_ProcessButtonCB;
1387
}
1388
}
1389
1390
void MenuSetup_VS_StartMatch(void)
1391
{
1392
EntityCompetitionSession *session = CompetitionSession_GetSession();
1393
EntityMenuParam *param = MenuParam_GetParam();
1394
1395
sprintf(param->menuTag, "Competition Round");
1396
session->stageIndex = MenuSetup->competitionZones->buttonID;
1397
session->zoneID = param->vsZoneID;
1398
session->actID = param->vsActID;
1399
1400
RSDK.SetScene("Mania Mode", "");
1401
SceneInfo->listPos += TimeAttackData_GetManiaListPos(param->vsZoneID, param->vsActID, CHAR_SONIC);
1402
1403
SaveGame_ResetPlayerState();
1404
1405
// Bug Details(?):
1406
// sizeof(globals->noSaveSlot) and sizeof(saveData) is 4096 (sizeof(int32) * 0x400)
1407
// but the memset size is only 1024 (sizeof(uint8) * 0x400)
1408
// so only about 1/4th of the save slot is cleared, though nothin uses the extra space so it's not a big deal
1409
memset(globals->noSaveSlot, 0, 0x400);
1410
1411
globals->continues = 0;
1412
globals->saveSlotID = NO_SAVE_SLOT;
1413
globals->gameMode = MODE_COMPETITION;
1414
globals->medalMods = 0;
1415
1416
globals->playerID = ID_NONE;
1417
for (int32 i = 0; i < COMPETITION_PLAYER_COUNT; ++i) globals->playerID |= session->playerID[i] << (8 * i);
1418
1419
globals->itemMode = session->itemMode;
1420
1421
RSDK.LoadScene();
1422
}
1423
1424
void MenuSetup_VS_StartMatch_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_VS_StartMatch, 32); }
1425
1426
void MenuSetup_VS_RulesButton_ActionCB(void)
1427
{
1428
EntityUIControl *compControl = MenuSetup->competition;
1429
EntityUIControl *rulesControl = MenuSetup->competitionRules;
1430
EntityCompetitionSession *session = CompetitionSession_GetSession();
1431
1432
int32 matchCount = 0;
1433
foreach_all(UIVsRoundPicker, vsRoundPicker)
1434
{
1435
matchCount = vsRoundPicker->val;
1436
foreach_break;
1437
}
1438
1439
int32 itemMode = ITEMS_FIXED;
1440
switch (rulesControl->buttons[0]->selection) {
1441
default: break;
1442
case 0: itemMode = ITEMS_FIXED; break;
1443
case 1: itemMode = ITEMS_TELEPORT; break;
1444
case 2: itemMode = ITEMS_RANDOM; break;
1445
}
1446
1447
CompetitionSession_ResetOptions();
1448
1449
session->matchCount = matchCount;
1450
session->inMatch = true;
1451
session->itemMode = itemMode;
1452
1453
session->playerCount = 2;
1454
1455
EntityUIVsCharSelector *charSel = (EntityUIVsCharSelector *)compControl->buttons[0];
1456
switch (charSel->frameID) {
1457
case 0: session->playerID[0] = ID_SONIC; break;
1458
case 1: session->playerID[0] = ID_TAILS; break;
1459
case 2: session->playerID[0] = ID_KNUCKLES; break;
1460
default: break;
1461
}
1462
1463
charSel = (EntityUIVsCharSelector *)compControl->buttons[1];
1464
switch (charSel->frameID) {
1465
case 0: session->playerID[1] = ID_SONIC; break;
1466
case 1: session->playerID[1] = ID_TAILS; break;
1467
case 2: session->playerID[1] = ID_KNUCKLES; break;
1468
default: break;
1469
}
1470
1471
EntityUIControl *zoneControl = MenuSetup->competitionZones;
1472
zoneControl->position = zoneControl->startPos;
1473
zoneControl->targetPos.x = zoneControl->startPos.x;
1474
zoneControl->targetPos.y = zoneControl->startPos.y;
1475
zoneControl->buttonID = 0;
1476
1477
foreach_all(UIVsZoneButton, zoneButton)
1478
{
1479
zoneButton->xOut = !GameProgress_GetZoneUnlocked(zoneButton->zoneID);
1480
zoneButton->obfuscate = zoneButton->xOut;
1481
}
1482
1483
UIControl_MatchMenuTag("Competition Zones");
1484
}
1485
1486
void MenuSetup_VS_OpenCompTotal(void) { UIControl_MatchMenuTag("Competition Total"); }
1487
1488
void MenuSetup_VS_Round_ProcessButtonCB(void)
1489
{
1490
EntityCompetitionSession *session = CompetitionSession_GetSession();
1491
1492
if (UIControl->confirmPress[0] || UIControl->confirmPress[1] || UIControl->confirmPress[2] || UIControl->confirmPress[3]) {
1493
bool32 toCompTotal = false;
1494
1495
int32 activePlayers = 0;
1496
for (int32 p = 0; p < COMPETITION_PLAYER_COUNT; ++p) {
1497
if (session->lives[p] > 0)
1498
activePlayers++;
1499
1500
if (session->wins[p] > (session->matchCount >> 1))
1501
toCompTotal = true;
1502
}
1503
1504
if (toCompTotal || activePlayers < 2 || session->matchID >= session->matchCount)
1505
UITransition_StartTransition(MenuSetup_VS_OpenCompTotal, 0);
1506
else
1507
UITransition_StartTransition(MenuSetup_VS_OpenCompZones, 0);
1508
1509
RSDK.PlaySfx(UIWidgets->sfxAccept, false, 255);
1510
UIControl->inputLocked = true;
1511
}
1512
}
1513
1514
void MenuSetup_VS_Round_MenuSetupCB(void)
1515
{
1516
EntityCompetitionSession *session = CompetitionSession_GetSession();
1517
EntityUIControl *roundControl = MenuSetup->competitionRound;
1518
1519
int32 matchWinner = session->matchWinner[session->matchID - 1];
1520
1521
int32 winner = 0;
1522
if (matchWinner > 1)
1523
winner = matchWinner - 1;
1524
1525
String roundLabelStr;
1526
INIT_STRING(roundLabelStr);
1527
1528
char roundLabel[0x100];
1529
memset(roundLabel, 0, sizeof(roundLabel));
1530
1531
Localization_GetZoneName(&roundLabelStr, session->zoneID);
1532
if (session->zoneID < 12) {
1533
char buf[16];
1534
sprintf(buf, " ZONE %d", session->actID + 1);
1535
RSDK.AppendText(&roundLabelStr, buf);
1536
}
1537
1538
RSDK.GetCString(roundLabel, &roundLabelStr);
1539
UIInfoLabel_SetText(MenuSetup->roundLabel, roundLabel);
1540
1541
EntityUIVsScoreboard *scoreboard = MenuSetup->roundScoreboard;
1542
UIVsScoreboard_SetScores(scoreboard, session->wins[0], session->wins[1]);
1543
scoreboard->showWinner = matchWinner != 0;
1544
scoreboard->winnerID = winner;
1545
1546
if (matchWinner) {
1547
LogHelpers_Print("Announce_CharWins(%d)", session->playerID[winner]);
1548
1549
EntityAnnouncer *announcer = CREATE_ENTITY(Announcer, NULL, 0, 0);
1550
announcer->state = Announcer_State_AnnounceWinPlayer;
1551
announcer->playerID = session->playerID[winner];
1552
}
1553
1554
uint32 times[PLAYER_COUNT];
1555
for (int32 p = 0; p < COMPETITION_PLAYER_COUNT; ++p) {
1556
times[p] = session->time[p].milliseconds + 100 * (session->time[p].seconds + 4 * (16 * session->time[p].minutes - session->time[p].minutes));
1557
}
1558
1559
char buffer[0x40];
1560
foreach_all(UIVsResults, results)
1561
{
1562
if (UIControl_ContainsPos(roundControl, &results->position)) {
1563
int32 p = results->playerID;
1564
int32 r = results->playerID ^ 1;
1565
1566
results->isWinner = p == winner && scoreboard->showWinner;
1567
1568
memset(buffer, 0, sizeof(buffer));
1569
1570
sprintf(buffer, "%d", session->rings[p]);
1571
if (!SceneInfo->inEditor) {
1572
RSDK.InitString(&results->rowText[0], buffer, 0);
1573
RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[0]);
1574
}
1575
1576
sprintf(buffer, "%d", session->totalRings[p]);
1577
if (!SceneInfo->inEditor) {
1578
RSDK.InitString(&results->rowText[1], buffer, 0);
1579
RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[1]);
1580
}
1581
1582
sprintf(buffer, "%d", session->score[p]);
1583
if (!SceneInfo->inEditor) {
1584
RSDK.InitString(&results->rowText[2], buffer, 0);
1585
RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[2]);
1586
}
1587
1588
sprintf(buffer, "%d", session->items[p]);
1589
if (!SceneInfo->inEditor) {
1590
RSDK.InitString(&results->rowText[3], buffer, 0);
1591
RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[3]);
1592
}
1593
1594
sprintf(buffer, "%d'%02d\"%02d", session->time[p].minutes, session->time[p].seconds, session->time[p].milliseconds);
1595
if (!SceneInfo->inEditor) {
1596
RSDK.InitString(&results->rowText[4], buffer, 0);
1597
RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[4]);
1598
}
1599
1600
if (session->lives[p]) {
1601
if (session->lives[r]) {
1602
results->row0Highlight = session->rings[p] > session->rings[r];
1603
results->row1Highlight = session->totalRings[p] > session->totalRings[r];
1604
results->row2Highlight = session->score[p] > session->score[r];
1605
results->row3Highlight = session->items[p] > session->items[r];
1606
results->row4Highlight = times[p] > 0 && times[p] < times[r];
1607
}
1608
else {
1609
results->row0Highlight = true;
1610
results->row1Highlight = true;
1611
results->row2Highlight = true;
1612
results->row3Highlight = true;
1613
results->row4Highlight = true;
1614
}
1615
}
1616
}
1617
}
1618
}
1619
1620
void MenuSetup_VS_GotoCompetition(void) { UIControl_MatchMenuTag("Competition"); }
1621
1622
void MenuSetup_VS_Total_ProcessButtonCB(void)
1623
{
1624
EntityCompetitionSession *session = CompetitionSession_GetSession();
1625
1626
if (UIControl->anyConfirmPress) {
1627
int32 mostWins = 0;
1628
for (int32 p = 0; p < session->playerCount; ++p) {
1629
if (session->wins[p] > mostWins)
1630
mostWins = session->wins[p];
1631
}
1632
1633
int32 winnerCount = 0;
1634
for (int32 p = 0; p < session->playerCount; ++p) {
1635
if (session->wins[p] == mostWins)
1636
winnerCount++;
1637
}
1638
1639
if (winnerCount > 1) {
1640
MenuSetup_StartTransition(MenuSetup_VS_StartPuyoMatch, 32);
1641
}
1642
else {
1643
CompetitionSession_ResetOptions();
1644
UITransition_StartTransition(MenuSetup_VS_GotoCompetition, 0);
1645
}
1646
1647
RSDK.PlaySfx(UIWidgets->sfxAccept, false, 255);
1648
UIControl->inputLocked = true;
1649
}
1650
}
1651
1652
void MenuSetup_VS_Total_MenuSetupCB(void)
1653
{
1654
EntityUIControl *totalControl = MenuSetup->competitionTotal;
1655
EntityCompetitionSession *session = CompetitionSession_GetSession();
1656
1657
MenuSetup->vsTotalTimer = 120;
1658
1659
totalControl->targetPos.y = totalControl->startPos.y;
1660
totalControl->position.y = totalControl->startPos.y;
1661
1662
String string;
1663
INIT_STRING(string);
1664
1665
EntityUIInfoLabel *label = MenuSetup->totalLabel;
1666
Localization_GetString(&string, STR_COMPTOTAL);
1667
UIInfoLabel_SetString(label, &string);
1668
1669
int32 highestScore = 0;
1670
for (int32 p = 0; p < session->playerCount; ++p) {
1671
if (session->wins[p] > highestScore)
1672
highestScore = session->wins[p];
1673
}
1674
1675
EntityUIVsScoreboard *scoreboard = MenuSetup->roundScoreboard;
1676
UIVsScoreboard_SetScores(scoreboard, session->wins[0], session->wins[1]);
1677
scoreboard->showWinner = session->wins[0] != session->wins[1];
1678
scoreboard->winnerID = session->wins[1] > session->wins[0];
1679
1680
if (scoreboard->showWinner) {
1681
LogHelpers_Print("Announce_WinnerIs(%d)", scoreboard->winnerID);
1682
EntityAnnouncer *announcer = CREATE_ENTITY(Announcer, NULL, 0, 0);
1683
announcer->state = Announcer_State_AnnounceWinner;
1684
announcer->playerID = scoreboard->winnerID;
1685
}
1686
1687
foreach_all(UIVsResults, results)
1688
{
1689
if (UIControl_ContainsPos(totalControl, &results->position)) {
1690
bool32 *highlight = &results->row0Highlight;
1691
1692
results->numRows = session->matchCount;
1693
results->isWinner = results->playerID == scoreboard->winnerID;
1694
1695
for (int32 r = 0; r < results->numRows; ++r) {
1696
char buffer[0x40];
1697
sprintf(buffer, "%d", session->matchWinner[r]);
1698
1699
if (!SceneInfo->inEditor) {
1700
RSDK.InitString(&results->rowText[r], buffer, 0);
1701
RSDK.SetSpriteString(UIVsResults->aniFrames, 18, &results->rowText[r]);
1702
}
1703
1704
highlight[r] = false;
1705
if (session->matchWinner[r])
1706
highlight[r] = (session->matchWinner[r] - 1) == results->playerID;
1707
}
1708
}
1709
}
1710
}
1711
1712
void MenuSetup_VS_Total_MenuUpdateCB(void)
1713
{
1714
EntityUIControl *totalControl = MenuSetup->competitionTotal;
1715
1716
if (totalControl->active == ACTIVE_ALWAYS) {
1717
if (totalControl->position.y == totalControl->targetPos.y) {
1718
if (MenuSetup->vsTotalTimer <= 0) {
1719
int32 targetPos = totalControl->startPos.y;
1720
if (totalControl->targetPos.y == totalControl->startPos.y) {
1721
EntityUIVsResults *button = (EntityUIVsResults *)totalControl->buttons[0];
1722
1723
if (button && button->size.y + button->position.y - 0x708000 > totalControl->startPos.y) {
1724
targetPos = button->size.y + button->position.y - 0x708000;
1725
}
1726
}
1727
1728
totalControl->targetPos.y = targetPos;
1729
MenuSetup->vsTotalTimer = 120;
1730
}
1731
else {
1732
MenuSetup->vsTotalTimer--;
1733
}
1734
}
1735
}
1736
}
1737
1738
void MenuSetup_VS_ExitComp_TransitionCB(void)
1739
{
1740
EntityUIControl *control = MenuSetup->competition;
1741
EntityUIControl *zoneControl = MenuSetup->competitionZones;
1742
1743
UIControl_SetInactiveMenu(zoneControl);
1744
UIControl_SetActiveMenu(control);
1745
CompetitionSession_ResetOptions();
1746
1747
zoneControl->childHasFocus = false;
1748
1749
foreach_all(UIVsZoneButton, zoneButton)
1750
{
1751
zoneButton->xOut = !GameProgress_GetZoneUnlocked(zoneButton->zoneID);
1752
zoneButton->obfuscate = zoneButton->xOut;
1753
}
1754
}
1755
1756
void MenuSetup_VS_BackoutFromVsCharSelect_CB(void)
1757
{
1758
EntityUIControl *control = UIControl_GetUIControl();
1759
control->selectionDisabled = false;
1760
1761
UIControl_HandleMenuChange(&control->parentTag);
1762
}
1763
1764
bool32 MenuSetup_VS_BackoutFromVsCharSelect(void)
1765
{
1766
LogHelpers_Print("BackoutFromVsCharSelect()");
1767
EntityUIControl *control = MenuSetup->competition;
1768
1769
for (int32 i = 0; i < control->buttonCount; ++i) {
1770
EntityUIVsCharSelector *button = (EntityUIVsCharSelector *)control->buttons[i];
1771
if (button->classID == UIVsCharSelector->classID && button->prevSelected && UIControl->backPress[button->playerID]) {
1772
UITransition_StartTransition(MenuSetup_VS_BackoutFromVsCharSelect_CB, 0);
1773
return true;
1774
}
1775
}
1776
1777
if (!control->buttonCount) {
1778
control->selectionDisabled = true;
1779
1780
if (!UIControl->backPress[0] && UIControl->anyBackPress) {
1781
UITransition_StartTransition(MenuSetup_VS_BackoutFromVsCharSelect_CB, 0);
1782
return true;
1783
}
1784
}
1785
1786
return false;
1787
}
1788
1789
void MenuSetup_VS_ExitComp_YesCB(void) { UITransition_StartTransition(MenuSetup_VS_ExitComp_TransitionCB, 0); }
1790
1791
bool32 MenuSetup_VS_CompZones_BackPressCB(void)
1792
{
1793
String message;
1794
INIT_STRING(message);
1795
1796
Localization_GetString(&message, STR_EXITCOMP);
1797
UIDialog_CreateDialogYesNo(&message, MenuSetup_VS_ExitComp_YesCB, NULL, true, true);
1798
1799
return true;
1800
}
1801
1802
void MenuSetup_VS_StartPuyoMatch(void)
1803
{
1804
EntityMenuParam *param = MenuParam_GetParam();
1805
1806
TimeAttackData_Clear();
1807
1808
param->puyoSelection = PUYO_SELECTION_TIE_BREAKER;
1809
globals->gameMode = MODE_COMPETITION;
1810
strcpy(param->menuTag, "Competition Total");
1811
param->menuSelection = 0;
1812
1813
RSDK.SetScene("Extras", "Puyo Puyo");
1814
RSDK.LoadScene();
1815
}
1816
1817
// Options
1818
void MenuSetup_Options_VideoMenuButton_ActionCB(void)
1819
{
1820
if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV)
1821
UIControl_MatchMenuTag("Video WIN");
1822
else
1823
UIControl_MatchMenuTag("Video");
1824
}
1825
1826
void MenuSetup_Options_SoundMenuButton_ActionCB(void) { UIControl_MatchMenuTag("Sound"); }
1827
1828
void MenuSetup_Options_LanguageMenuButton_ActionCB(void) { UIControl_MatchMenuTag("Language"); }
1829
1830
void MenuSetup_Options_ControlsMenuButton_ActionCB(void)
1831
{
1832
int32 id = API_GetFilteredInputDeviceID(INPUT_NONE);
1833
int32 type = API_GetInputDeviceType(id);
1834
1835
switch (sku_platform) {
1836
case PLATFORM_DEV:
1837
case PLATFORM_PC:
1838
if (sku_platform == PLATFORM_DEV || type)
1839
UIControl_MatchMenuTag("Controls WIN");
1840
else
1841
UIControl_MatchMenuTag("Controls XB1");
1842
break;
1843
1844
case PLATFORM_PS4: UIControl_MatchMenuTag("Controls PS4"); break;
1845
1846
case PLATFORM_XB1: UIControl_MatchMenuTag("Controls XB1"); break;
1847
1848
case PLATFORM_SWITCH:
1849
switch (type) {
1850
case 1: UIControl_MatchMenuTag("Controls NX"); break;
1851
case 2: UIControl_MatchMenuTag("Controls NX Grip"); break;
1852
case 3: UIControl_MatchMenuTag("Controls NX Joycon"); break;
1853
case 4: UIControl_MatchMenuTag("Controls NX Pro"); break;
1854
default: break;
1855
}
1856
break;
1857
}
1858
}
1859
1860
void MenuSetup_Options_SetDefaultMappings_P1(void)
1861
{
1862
ControllerInfo[CONT_P1].keyUp.keyMap = KEYMAP_UP;
1863
ControllerInfo[CONT_P1].keyDown.keyMap = KEYMAP_DOWN;
1864
ControllerInfo[CONT_P1].keyLeft.keyMap = KEYMAP_LEFT;
1865
ControllerInfo[CONT_P1].keyRight.keyMap = KEYMAP_RIGHT;
1866
ControllerInfo[CONT_P1].keyA.keyMap = KEYMAP_A;
1867
ControllerInfo[CONT_P1].keyB.keyMap = KEYMAP_S;
1868
ControllerInfo[CONT_P1].keyC.keyMap = KEYMAP_NO_MAPPING;
1869
ControllerInfo[CONT_P1].keyX.keyMap = KEYMAP_Q;
1870
ControllerInfo[CONT_P1].keyY.keyMap = KEYMAP_W;
1871
ControllerInfo[CONT_P1].keyZ.keyMap = KEYMAP_NO_MAPPING;
1872
ControllerInfo[CONT_P1].keyStart.keyMap = KEYMAP_RETURN;
1873
ControllerInfo[CONT_P1].keySelect.keyMap = KEYMAP_TAB;
1874
}
1875
1876
void MenuSetup_Options_SetDefaultMappings_P2(void)
1877
{
1878
#if GAME_VERSION != VER_100
1879
ControllerInfo[CONT_P2].keyUp.keyMap = KEYMAP_NUMPAD8;
1880
ControllerInfo[CONT_P2].keyDown.keyMap = KEYMAP_NUMPAD5;
1881
ControllerInfo[CONT_P2].keyLeft.keyMap = KEYMAP_NUMPAD4;
1882
ControllerInfo[CONT_P2].keyRight.keyMap = KEYMAP_NUMPAD6;
1883
ControllerInfo[CONT_P2].keyA.keyMap = KEYMAP_J;
1884
ControllerInfo[CONT_P2].keyB.keyMap = KEYMAP_K;
1885
ControllerInfo[CONT_P2].keyC.keyMap = KEYMAP_NO_MAPPING;
1886
ControllerInfo[CONT_P2].keyX.keyMap = KEYMAP_U;
1887
ControllerInfo[CONT_P2].keyY.keyMap = KEYMAP_I;
1888
ControllerInfo[CONT_P2].keyZ.keyMap = KEYMAP_NO_MAPPING;
1889
ControllerInfo[CONT_P2].keyStart.keyMap = KEYMAP_OEM_4;
1890
ControllerInfo[CONT_P2].keySelect.keyMap = KEYMAP_OEM_6;
1891
#else
1892
ControllerInfo[CONT_P2].keyUp.keyMap = KEYMAP_I;
1893
ControllerInfo[CONT_P2].keyDown.keyMap = KEYMAP_K;
1894
ControllerInfo[CONT_P2].keyLeft.keyMap = KEYMAP_J;
1895
ControllerInfo[CONT_P2].keyRight.keyMap = KEYMAP_L;
1896
ControllerInfo[CONT_P2].keyA.keyMap = KEYMAP_V;
1897
ControllerInfo[CONT_P2].keyB.keyMap = KEYMAP_B;
1898
ControllerInfo[CONT_P2].keyC.keyMap = KEYMAP_NO_MAPPING;
1899
ControllerInfo[CONT_P2].keyX.keyMap = KEYMAP_F;
1900
ControllerInfo[CONT_P2].keyY.keyMap = KEYMAP_G;
1901
ControllerInfo[CONT_P2].keyZ.keyMap = KEYMAP_NO_MAPPING;
1902
ControllerInfo[CONT_P2].keyStart.keyMap = KEYMAP_O;
1903
ControllerInfo[CONT_P2].keySelect.keyMap = KEYMAP_NO_MAPPING;
1904
#endif
1905
}
1906
1907
void MenuSetup_Options_SetupKBControlsMenu(int32 playerID)
1908
{
1909
EntityUIControl *control = MenuSetup->controls_KB;
1910
1911
foreach_all(UISubHeading, subHeading)
1912
{
1913
if (UIControl_ContainsPos(control, &subHeading->position)) {
1914
subHeading->frameID = playerID + 8;
1915
foreach_break;
1916
}
1917
}
1918
1919
for (int32 b = 0; b < control->buttonCount; ++b) {
1920
if (control->buttons[b]->classID == UIKeyBinder->classID) {
1921
EntityUIKeyBinder *binder = (EntityUIKeyBinder *)control->buttons[b];
1922
binder->inputID = playerID;
1923
}
1924
else if (control->buttons[b]->classID == UIButton->classID) {
1925
EntityUIButton *button = control->buttons[b];
1926
1927
if (playerID == 1)
1928
button->actionCB = MenuSetup_Options_SetDefaultMappings_P2;
1929
else if (playerID == 0)
1930
button->actionCB = MenuSetup_Options_SetDefaultMappings_P1;
1931
}
1932
}
1933
}
1934
1935
void MenuSetup_OptionsVideo_Win_MenuUpdateCB(void) { MenuSetup_OptionsVideo_Win_InitVideoOptionsMenu(); }
1936
1937
void MenuSetup_OptionsVideo_Win_InitVideoOptionsMenu(void)
1938
{
1939
if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV) {
1940
EntityUIControl *videoControl_Win = MenuSetup->video_win;
1941
OptionsRAM *optionsRAM = Options_GetOptionsRAM();
1942
Options_GetWinSize();
1943
1944
int32 options[7];
1945
1946
#if GAME_VERSION != VER_100
1947
options[0] = RSDK.GetVideoSetting(VIDEOSETTING_SHADERID); // filter
1948
options[1] = optionsRAM->windowSize; // window size
1949
options[2] = RSDK.GetVideoSetting(VIDEOSETTING_BORDERED); // bordered
1950
1951
options[3] = 0;
1952
if (!RSDK.GetVideoSetting(VIDEOSETTING_WINDOWED) || optionsRAM->windowSize == 4)
1953
options[3] = 1;
1954
1955
options[4] = 0; // fullscreen res
1956
options[5] = RSDK.GetVideoSetting(VIDEOSETTING_VSYNC); // vsync
1957
options[6] = RSDK.GetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED); // triple buffered
1958
#else
1959
options[0] = RSDK.GetVideoSetting(VIDEOSETTING_SHADERID); // filter
1960
options[1] = optionsRAM->windowSize; // window size
1961
options[2] = RSDK.GetVideoSetting(VIDEOSETTING_BORDERED); // bordered
1962
1963
options[3] = 0;
1964
if (!RSDK.GetVideoSetting(VIDEOSETTING_WINDOWED) || optionsRAM->windowSize == 4)
1965
options[3] = 1;
1966
1967
options[4] = RSDK.GetVideoSetting(VIDEOSETTING_VSYNC); // vsync
1968
options[5] = RSDK.GetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED); // triple buffered
1969
#endif
1970
1971
for (int32 i = 0; i < videoControl_Win->buttonCount; ++i) {
1972
EntityUIButton *button = videoControl_Win->buttons[i];
1973
1974
#if GAME_VERSION != VER_100
1975
if (i == 4) {
1976
EntityUIResPicker *resPicker = (EntityUIResPicker *)UIButton_GetChoicePtr(button, button->selection);
1977
UIResPicker_GetDisplayInfo(resPicker);
1978
}
1979
else if (i == 1) {
1980
EntityUIWinSize *winSize = (EntityUIWinSize *)UIButton_GetChoicePtr(button, button->selection);
1981
winSize->selection = RSDK.GetVideoSetting(VIDEOSETTING_WINDOW_HEIGHT) / SCREEN_YSIZE;
1982
}
1983
else if (button->selection != options[i]) {
1984
UIButton_SetChoiceSelection(button, options[i]);
1985
}
1986
#else
1987
if (button->selection != options[i]) {
1988
UIButton_SetChoiceSelection(button, options[i]);
1989
}
1990
#endif
1991
}
1992
}
1993
}
1994
1995
void MenuSetup_Options_OpenKBControlsMenu(void)
1996
{
1997
RSDK_THIS(UIButton);
1998
1999
EntityUIControl *control = MenuSetup->controls_win;
2000
2001
for (int32 i = 0; i < control->buttonCount; ++i) {
2002
if (self == control->buttons[i]) {
2003
MenuSetup_Options_SetupKBControlsMenu(i);
2004
UIControl_MatchMenuTag("Controls KB");
2005
break;
2006
}
2007
}
2008
}
2009
2010
void MenuSetup_Options_MenuSetupCB(void)
2011
{
2012
if (Options->changed) {
2013
UIWaitSpinner_StartWait();
2014
2015
Options_SaveFile(MenuSetup_Options_SaveOptionsCB_Load);
2016
}
2017
}
2018
2019
void MenuSetup_Options_SaveOptionsCB_Load(void) { UIWaitSpinner_FinishWait(); }
2020
2021
void MenuSetup_Options_LaunchManual(void)
2022
{
2023
RSDK.PlaySfx(UIWidgets->sfxAccept, false, 0xFF);
2024
API_LaunchManual();
2025
}
2026
2027
void MenuSetup_OptionsLanguage_LanguageButton_ActionCB(void)
2028
{
2029
OptionsRAM *options = Options_GetOptionsRAM();
2030
EntityUIControl *control = MenuSetup->language;
2031
2032
if (control->buttonID < 0)
2033
options->language = -1;
2034
else
2035
options->language = control->buttonID;
2036
2037
options->overrideLanguage = control->buttonID >= 0;
2038
2039
if (sku_platform == PLATFORM_PC || sku_platform == PLATFORM_DEV)
2040
RSDK.SetVideoSetting(VIDEOSETTING_LANGUAGE, control->buttonID);
2041
2042
Options->changed = true;
2043
2044
Localization->language = control->buttonID;
2045
control->startingID = control->buttonID;
2046
Localization->loaded = false;
2047
2048
Localization_LoadStrings();
2049
UIWidgets_ApplyLanguage();
2050
UIHeading_LoadSprites();
2051
2052
UIControl_MatchMenuTag("Options");
2053
}
2054
2055
void MenuSetup_OptionsVideo_ShaderButton_ActionCB(void)
2056
{
2057
RSDK_THIS(UIButton);
2058
2059
OptionsRAM *options = Options_GetOptionsRAM();
2060
2061
options->screenShader = self->selection;
2062
options->overrideShader = true;
2063
RSDK.SetVideoSetting(VIDEOSETTING_SHADERID, self->selection);
2064
2065
Options->changed = true;
2066
}
2067
2068
void MenuSetup_OptionsVideo_WindowScaleButton_ActionCB(void)
2069
{
2070
RSDK_THIS(UIButton);
2071
2072
OptionsRAM *options = Options_GetOptionsRAM();
2073
2074
if (self->selection != 4) {
2075
RSDK.SetVideoSetting(VIDEOSETTING_WINDOW_WIDTH, WIDE_SCR_XSIZE * (self->selection + 1));
2076
RSDK.SetVideoSetting(VIDEOSETTING_WINDOW_HEIGHT, SCREEN_YSIZE * (self->selection + 1));
2077
2078
options->windowSize = self->selection;
2079
Options->changed = true;
2080
}
2081
}
2082
2083
void MenuSetup_OptionsVideo_BorderlessButton_ActionCB(void)
2084
{
2085
RSDK_THIS(UIButton);
2086
2087
OptionsRAM *options = Options_GetOptionsRAM();
2088
2089
options->windowBorder = self->selection;
2090
RSDK.SetVideoSetting(VIDEOSETTING_BORDERED, self->selection);
2091
2092
RSDK.UpdateWindow();
2093
Options->changed = true;
2094
}
2095
2096
void MenuSetup_OptionsVideo_FullscreenButton_ActionCB(void)
2097
{
2098
RSDK_THIS(UIButton);
2099
2100
OptionsRAM *options = Options_GetOptionsRAM();
2101
2102
options->windowed = self->selection ^ 1;
2103
RSDK.SetVideoSetting(VIDEOSETTING_WINDOWED, options->windowed);
2104
2105
RSDK.UpdateWindow();
2106
Options->changed = true;
2107
}
2108
2109
void MenuSetup_OptionsVideo_VSyncButton_ActionCB(void)
2110
{
2111
RSDK_THIS(UIButton);
2112
2113
OptionsRAM *options = Options_GetOptionsRAM();
2114
2115
options->vSync = self->selection;
2116
RSDK.SetVideoSetting(VIDEOSETTING_VSYNC, self->selection);
2117
2118
Options->changed = true;
2119
}
2120
2121
void MenuSetup_OptionsVideo_TripleBufferButton_ActionCB(void)
2122
{
2123
RSDK_THIS(UIButton);
2124
2125
OptionsRAM *options = Options_GetOptionsRAM();
2126
2127
options->tripleBuffering = self->selection;
2128
RSDK.SetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED, self->selection);
2129
2130
Options->changed = true;
2131
}
2132
2133
void MenuSetup_OptionsVideo_UISlider_ChangedCB(void)
2134
{
2135
RSDK_THIS(UISlider);
2136
2137
OptionsRAM *options = Options_GetOptionsRAM();
2138
2139
// Bug Details (?):
2140
// what the hell is up with this???????
2141
// it'd only ever be 0 or 1 why are 0xF1, 0xF2, 0xF4, 0xF5 & 0xFC options?????
2142
// this is a CB for the slider why are the boolean values here???
2143
2144
bool32 value = self->frameID != 1;
2145
switch (value) {
2146
case 0xF1:
2147
options->windowed = self->sliderPos;
2148
RSDK.SetVideoSetting(VIDEOSETTING_WINDOWED, options->windowed);
2149
break;
2150
2151
case 0xF2:
2152
options->windowBorder = self->sliderPos;
2153
RSDK.SetVideoSetting(VIDEOSETTING_BORDERED, options->windowBorder);
2154
break;
2155
2156
case 0xF4:
2157
options->vSync = self->sliderPos;
2158
RSDK.SetVideoSetting(VIDEOSETTING_VSYNC, options->vSync);
2159
break;
2160
2161
case 0xF5:
2162
options->tripleBuffering = self->sliderPos;
2163
RSDK.SetVideoSetting(VIDEOSETTING_TRIPLEBUFFERED, options->tripleBuffering);
2164
break;
2165
2166
case 0xFC:
2167
options->screenShader = self->sliderPos;
2168
options->overrideShader = true;
2169
RSDK.SetVideoSetting(VIDEOSETTING_SHADERID, options->screenShader);
2170
2171
RSDK.UpdateWindow();
2172
break;
2173
2174
case 0:
2175
options->volMusic = self->sliderPos;
2176
options->overrideMusicVol = true;
2177
RSDK.SetVideoSetting(VIDEOSETTING_STREAM_VOL, options->volMusic);
2178
break;
2179
2180
case 1:
2181
options->volSfx = self->sliderPos;
2182
options->overrideSfxVol = true;
2183
RSDK.SetVideoSetting(VIDEOSETTING_SFX_VOL, options->volSfx);
2184
break;
2185
2186
default: break;
2187
}
2188
Options->changed = true;
2189
}
2190
2191
void MenuSetup_OpenExtrasMenu_ActionCB(void) { UIControl_MatchMenuTag("Extras"); }
2192
2193
// Extras
2194
void MenuSetup_Extras_ProcessButtonCB(void) { UIControl_ProcessButtonInput(); }
2195
2196
void MenuSetup_Extras_Start_Puyo_vsAI(void)
2197
{
2198
EntityMenuParam *param = MenuParam_GetParam();
2199
2200
TimeAttackData_Clear();
2201
2202
param->puyoSelection = PUYO_SELECTION_VS_CPU;
2203
strcpy(param->menuTag, "Extras");
2204
param->menuSelection = EXTRAS_SELECTION_PUYO;
2205
2206
RSDK.SetScene("Extras", "Puyo Puyo");
2207
RSDK.LoadScene();
2208
}
2209
2210
void MenuSetup_Extras_Puyo_vsAI_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_Puyo_vsAI, 32); }
2211
2212
void MenuSetup_Extras_Start_Puyo_vs2P(void)
2213
{
2214
EntityMenuParam *param = MenuParam_GetParam();
2215
2216
TimeAttackData_Clear();
2217
2218
param->puyoSelection = PUYO_SELECTION_VS_2P;
2219
strcpy(param->menuTag, "Extras");
2220
param->menuSelection = EXTRAS_SELECTION_PUYO;
2221
2222
RSDK.SetScene("Extras", "Puyo Puyo");
2223
RSDK.LoadScene();
2224
}
2225
2226
void MenuSetup_Extras_Puyo_vs2P_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_Puyo_vs2P, 32); }
2227
2228
void MenuSetup_Extras_Start_Credits(void)
2229
{
2230
EntityMenuParam *param = MenuParam_GetParam();
2231
2232
TimeAttackData_Clear();
2233
2234
param->bssSelection = CREDITS_SELECTION_EXTRAS;
2235
strcpy(param->menuTag, "Extras");
2236
param->menuSelection = EXTRAS_SELECTION_CREDITS;
2237
param->creditsReturnToMenu = true;
2238
2239
RSDK.SetScene("Presentation", "Credits");
2240
RSDK.LoadScene();
2241
}
2242
2243
void MenuSetup_Extras_Credits_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_Credits, 32); }
2244
2245
void MenuSetup_Extras_StartDAGarden(void)
2246
{
2247
EntityMenuParam *param = MenuParam_GetParam();
2248
2249
TimeAttackData_Clear();
2250
2251
strcpy(param->menuTag, "Extras");
2252
param->menuSelection = EXTRAS_SELECTION_DAGARDEN;
2253
2254
RSDK.SetScene("Extras", "D.A. Garden");
2255
RSDK.LoadScene();
2256
}
2257
2258
void MenuSetup_Extras_DAGarden_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_StartDAGarden, 32); }
2259
2260
void MenuSetup_Extras_Start_BSS_3K(void)
2261
{
2262
EntityMenuParam *param = MenuParam_GetParam();
2263
2264
TimeAttackData_Clear();
2265
2266
param->bssSelection = BSS_SELECTION_EXTRAS;
2267
strcpy(param->menuTag, "Extras");
2268
param->menuSelection = EXTRAS_SELECTION_BSS;
2269
2270
RSDK.SetScene("Blue Spheres", "Random");
2271
RSDK.LoadScene();
2272
}
2273
2274
void MenuSetup_Extras_BSS_3K_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_BSS_3K, 32); }
2275
2276
void MenuSetup_Extras_Start_BSS_Mania(void)
2277
{
2278
EntityMenuParam *param = MenuParam_GetParam();
2279
2280
TimeAttackData_Clear();
2281
2282
param->bssSelection = BSS_SELECTION_EXTRAS;
2283
strcpy(param->menuTag, "Extras");
2284
param->menuSelection = EXTRAS_SELECTION_BSS;
2285
2286
RSDK.SetScene("Blue Spheres", "Random 2");
2287
RSDK.LoadScene();
2288
}
2289
2290
void MenuSetup_Extras_BSS_Mania_ActionCB(void) { MenuSetup_StartTransition(MenuSetup_Extras_Start_BSS_Mania, 32); }
2291
2292
#endif
2293
2294
#if GAME_INCLUDE_EDITOR
2295
void MenuSetup_EditorDraw(void) {}
2296
2297
void MenuSetup_EditorLoad(void) {}
2298
#endif
2299
2300
void MenuSetup_Serialize(void) {}
2301
2302