Alchemy
Loading...
Searching...
No Matches

party_commands.c

Go to the documentation of this file.
1/// @file
2/// Collecting the party's battle commands.
3/// Part of battle_command.c, the menu object, compiled only through it.
4
6
7/// Returns the target selection category for an ability's effect.
8/// 0 other, 1 restore HP, 2 restore PP, 3 cure poison, 4 cure status ailments,
9/// 5 revive, 6 cure all status ailments.
10/// act: ability data
12 s32 signedEffect;
13 s32 abilityKind;
14 s32 targetKind;
15 u8 effect;
16
17 targetKind = 0;
18 abilityKind = act->flags & ABILITY_KIND_MASK;
19 if (abilityKind == ABILITY_KIND_HEAL_HP)
20 targetKind = 1;
21 if (abilityKind == ABILITY_KIND_HEAL_PP)
22 targetKind = 2;
23 signedEffect = (s8)act->effect;
24 effect = signedEffect;
25 if (effect == ABILITY_EFFECT_CURE_POISON)
26 targetKind = 3;
27 if (effect == ABILITY_EFFECT_RESTORE)
28 targetKind = 4;
29 if (effect == ABILITY_EFFECT_CURE_ALL)
30 targetKind = 6;
31 if (Battle_IsReviveEffectFar(act->effect) != 0)
32 targetKind = 5;
33 return targetKind;
34}
35
36/// Collects commands in party order, including target, cost and randomized
37/// priority. Cancelling returns to the preceding choice; linked battles
38/// exchange completion signatures before releasing the command UI.
40 u16 *actors, s32 commandCount) {
41 struct BattleMenuWork *state;
42 struct BattleWork *battle;
43 struct BattleWork *linkBattle;
44 u16 *peerSignature;
45 u16 *transferWords;
47 struct BattleUnit *unit;
48 struct UiWindow *commandWindow;
49 struct MenuSprite *iconSprite;
50 u16 signatureHeader[2];
51 s32 target;
52 s32 actorId;
53 s32 mode;
54 s32 commandKind;
55 s32 parameter;
56 s32 largeIconSlot;
57 s32 smallIconSlot;
58 s32 missedLinkFrames;
59 s32 commandIndex;
60 s32 k;
61 s32 priority;
62
63 // An empty ID list dims every party panel before the next actor is chosen.
64 void BattleMenu_ClearPartyHighlights(void) {
65 u16 data[2];
66 data[0] = 0xff;
69 }
70
71 // Set up the shared command UI before the optional link handshake.
72 target = 256;
73 commandKind = 0;
74 parameter = 0;
75 largeIconSlot = VramCache_AllocEntry(1024);
76 smallIconSlot = VramCache_AllocEntry(512);
77 state = Runtime_AllocateBlock(57, 260);
78 Resource_LoadIndexedIntoBuffer(largeIconSlot, 0);
80 Link_DrawShiftedTilePair(0x06006680);
82 battle = gBattleWork;
83 for (k = 0; k < 8; k++) {
84 state->chosenDjinn[k] = 0x80000000;
85 }
86 for (k = 0; k < 3; k++) {
87 state->iconShown[k] = 0;
88 }
89 state->targetSceneOffset = 0;
90 state->sceneOffset = 0;
91 state->timer = -1;
92 state->commandSelection[0] = 0;
93 state->commandSelection[1] = 0;
94 state->linkTimer = 0;
95 state->timerHidden = 0;
96 state->timerWindow = 0;
97 // Both peers announce the command-entry phase before accepting commands.
98 if (battle->twoSided != 0) {
99 state->linkTimer = 1;
100 transferWords = (u16 *)gSerialTransfer.payload;
101 transferWords[4] = 'V';
102 transferWords[5] = 'S';
103 transferWords[6] = 'S';
104 transferWords[7] = 'T';
105 missedLinkFrames = 0;
106 for (;;) {
107 peerSignature = (u16 *)&gLinkPeerSignatures[battle->linkSide ^ 1];
108 if (battle->linkPaused != 0) {
109 commandCount = -1;
110 state->linkTimer = 0;
111 break;
112 }
113 if ((gLinkStatus & 3) != 3) {
114 if (++missedLinkFrames > 24) {
115 commandCount = -1;
116 state->linkTimer = 0;
117 break;
118 }
119 } else {
120 missedLinkFrames = 0;
121 if (peerSignature[4] == 'V' && peerSignature[5] == 'S' &&
122 peerSignature[6] == 'S' && peerSignature[7] == 'T') {
123 break;
124 }
125 if (peerSignature[4] == 'E' && peerSignature[5] == 'D' &&
126 peerSignature[6] == 'V' && peerSignature[7] == 'S') {
127 break;
128 }
129 if (!(peerSignature[0] == 'E' && peerSignature[1] == 'X' &&
130 peerSignature[2] == 'E' && peerSignature[3] == 'C')) {
131 commandCount = -1;
132 state->linkTimer = 0;
133 break;
134 }
135 }
136 WaitFrames(1);
137 }
138 }
140
141 while (1) {
142 BattleMenu_ClearPartyHighlights();
143 state->iconShown[2] = 0;
144 state->commandActor = -1;
145 state->tutorialStep = 0;
147 state->tutorialStep = 1;
148 state->tutorialDelay = 60;
149 }
150 if (commandCount > 0) {
151 mode = Menu_RunCommandRow(0);
152 } else {
153 mode = 14;
154 }
155 if (mode == 7) {
156 void *block;
157 s32 selection;
158 s32 handle;
159
160 block = MemAlloc(12);
161 if (gDebugMode != 0 && (gKeysHeld & KEY_START) != 0) {
162 selection = 2;
163 } else {
164 selection = 1;
165 }
166 handle = BattleParty_ListActorIdsFar(selection, block);
167 WaitFrames(1);
168 Ui_RunOwnerStatusScreen(block, handle, *(u16 *)block);
169 MemFree(block);
170 continue;
171 }
172 if (mode == 4) {
174 continue;
175 }
176 commandCount = 1;
177 command = commands;
178 command->unitId = actors[0];
179 command->priority = 0x7ffe;
180 command->command = 99;
181 command->parameter = 0;
182 command->target = 256;
183 break;
184 }
185 if (mode != 14) {
186 break;
187 }
189 commandIndex = 0;
190 if (commandIndex >= commandCount) {
191 break;
192 }
193
194 for (;;) {
195 if (commandIndex == 0) {
197 } else {
198 s32 k;
199
200 for (k = 0; k < 4; k++) {
201 state->standbyDjinn[commandIndex][k] =
202 state->standbyDjinn[commandIndex - 1][k];
203 }
204 }
205
206 command = &commands[commandIndex];
207 actorId = actors[commandIndex];
208 // UB: UnitGetFar returns a pointer, not the cast's doubleword result.
209#ifdef UBFIX
210 unit = UnitGetFar(actorId);
211#else
212 /* FAKEMATCH: called through a cast as returning a doubleword, the call
213 * also sets r1, so sched2 loads i * 2 before in, as native; by its
214 * prototype, 2 instructions differ in tbs-en. */
215 unit = (struct BattleUnit *)(s32)((s64 (*)(s32))UnitGetFar)(actorId);
216#endif
219 iconSprite = &gLinkCountdownWork->icons[2];
220 iconSprite->oam.word.attr01 = 0x80000400;
221 iconSprite->oam.word.attr23 = 0;
222 iconSprite->oam.f.tile =
223 UiGlyph_LoadPortrait(unit->classId, smallIconSlot);
224 iconSprite->oam.f.x = BATTLE_CLASS_ICON_X;
225 iconSprite->oam.f.y = 0x80;
226 iconSprite->oam.f.palette = 14;
227 state->iconShown[2] = 1;
228
229 mark_visible:
232 gLinkCountdownWork->chosenDjinn[commandIndex] = 0x80000000;
233 /* FAKEMATCH(dead): twelve dead stores restore the native frame's spill
234 * slots at sp+24 to sp+32; without them, 26 of 1727 instructions differ
235 * in tbs-en. */
236 signatureHeader[0] = 0;
237 signatureHeader[0] = 0;
238 signatureHeader[0] = 0;
239 signatureHeader[0] = 0;
240 signatureHeader[0] = 0;
241 signatureHeader[0] = 0;
242 signatureHeader[0] = 0;
243 signatureHeader[0] = 0;
244 signatureHeader[0] = 0;
245 signatureHeader[0] = 0;
246 signatureHeader[0] = 0;
247 signatureHeader[0] = 0;
248 signatureHeader[0] = (u16)actorId;
249 signatureHeader[1] = 255;
250 BattlePres_SetActorModesFar(signatureHeader, 1);
251 BattleLayout_HighlightPartyPanels(signatureHeader);
252 WaitFrames(1);
253 mode = Menu_RunCommandRow(1);
254 WaitFrames(1);
255 if (mode == -2) {
256 void *block;
257 s32 handle;
258
259 block = MemAlloc(12);
260 handle = BattleParty_ListActorIdsFar(1, block);
261 state->iconShown[2] = 0;
262 WaitFrames(1);
263 Ui_RunOwnerStatusScreen(block, handle, actorId);
264 state->iconShown[2] = 1;
265 MemFree(block);
266 continue;
267 }
268 BattlePres_SetActorModesFar(signatureHeader, 0);
269 if (mode == -1) {
270 if (commandIndex == 0) {
271 break;
272 }
273 commandIndex--;
274 continue;
275 }
276
277 if (gLinkCountdownWork->timer == 0) {
278 mode = 3;
279 }
280 iconSprite = &gLinkCountdownWork->icons[0];
281 iconSprite->oam.word.attr23 = 0;
282 iconSprite->oam.word.attr01 = 0x80002400;
283 iconSprite->oam.f.tile =
284 Resource_LoadIndexedIntoBuffer(largeIconSlot, mode);
285 if (mode == 15) {
286 iconSprite->oam.f.x = 128;
287 } else {
288 iconSprite->oam.f.x = 96;
289 }
290 iconSprite->oam.f.y = 136;
291 state->iconShown[0] = 1;
292 switch (mode) {
293 case 0:
294 commandWindow = UiWindow_Create(11, 17, 11, 3, 6);
295 UiText_DrawCharacterAtOffset(MsgCommandName, commandWindow,
297 state->icons[0].oam.f.x = 64;
299 mode = BattleTarget_RunSelection(actorId, 1, 1, 0);
300 UiWork_Finalize(commandWindow, 1);
301 if (mode == -1) {
302 goto mark_visible;
303 }
304 commandKind = 0;
305 target = mode;
306 command->range = 1;
307 break;
308
309 case 1: {
310 struct MenuSprite *iconSprite;
311 struct BattleAct *ability;
312 struct UiRenderWork *ui;
313 u16 *list;
314 u8 *pick;
315 s32 cost;
316 s32 handle;
317 s32 cnt;
318 s32 k;
319 s32 entryValue;
320
322 mode = 0;
324 psynergy_menu:
325 list = state->listAbilities;
326 pick = state->listSlots;
327 state->icons[0].oam.f.x = 48;
328 cnt = 0;
329 k = 0;
330 entryValue = unit->actionSlots[k].encodedAction & ACTION_ID_MASK;
331 if (entryValue != 0) {
332 do {
333 if ((BattleActGet(entryValue)->flags & 0x80) != 0) {
334 pick[cnt] = k;
335 list[cnt] = entryValue;
336 cnt++;
337 }
338 k++;
339 if (k == 32) {
340 break;
341 }
342 entryValue = unit->actionSlots[k].encodedAction & ACTION_ID_MASK;
343 } while (entryValue != 0);
344 }
345 pick[cnt] = 0;
346 list[cnt] = 0;
347 mode = BattleMenu_RunActionSelection(actorId, list, cnt);
348 if (mode == -1) {
349 goto mark_visible;
350 }
351 parameter =
353 ability = BattleActGet(parameter);
354 cost = ability->range;
355 iconSprite = &state->icons[1];
356 handle = VramCache_AllocEntry(128);
357 ui = UI_WORK;
358 commandWindow = UiWindow_Create(8, 17, 18, 3, 6);
359 state->icons[0].oam.f.x = 40;
360 iconSprite->oam.word.attr01 = 0x40000400;
361 iconSprite->oam.word.attr23 = 0;
362 iconSprite->oam.f.x = commandWindow->x * 8 + 8;
363 iconSprite->oam.f.y = commandWindow->y * 8 + 4;
364 /* FAKEMATCH(barrier): counted as 4 bytes, the empty asm puts the pool
365 * after mov r1, r10 as native (constant 40); without it, 13 of 1727
366 * instructions differ in tbs-en. */
367 __asm__ volatile("");
368 iconSprite->oam.f.tile =
369 Resource_LoadIndexedEntryToBuffer(parameter, handle);
370 state->iconShown[1] = 1;
371 ui->level = 5;
372 if ((s32)ability->ppCost > (s32)unit->pp) {
374 } else if (unit->psySeal != 0) {
376 }
377 UiText_DrawCharacterAtOffset(parameter + MsgAbilityName, commandWindow,
378 16, 0);
379 UiText_DrawNumberAtOffset(ability->ppCost, 2, commandWindow, 104, 0);
380 ui->level = 15;
382 UiWindow_SetTilemapEntry(commandWindow, 61471, 11, 0, 0);
384 0, 0);
385 if (ability->element != 4) {
386 UiWindow_SetTilemapEntry(commandWindow, ability->element + 20481, 15,
387 0, 0);
388 }
389 command->range = cost;
392 actorId, ability->targetMode, cost,
393 Battle_ClassifyEntryKind((const struct BattleAct *)ability));
394 state->iconShown[1] = 0;
395 Resource_ResetEntry(handle);
396 UiWork_Finalize(commandWindow, 1);
397 if (mode == -1) {
398 goto psynergy_menu;
399 }
400 commandKind = 1;
401 target = mode;
402 break;
403 }
404
405 case 16: {
406 const struct SummonDefinition *summon;
407 struct BattleAct *ability;
408 struct MenuSprite *iconSprite;
409 s32 handle;
410 s32 ok;
411 s32 j;
412 s32 n;
413
415 BATTLE_MENU_SET_CURSOR(0, 0, 0);
416 djinn_menu:
417 state->icons[0].oam.f.x = BATTLE_SUMMON_ICON_X;
418 BattleLayout_HighlightPartyPanels(signatureHeader);
419 mode = SummonMenu_SelectSummon(0, 0, state->standbyDjinn[commandIndex]);
420 BattleLayout_HighlightPartyPanels(signatureHeader);
421 if (mode == -1) {
422 goto mark_visible;
423 }
424 commandKind = 6;
425 parameter = mode;
426 WaitFrames(1);
427 iconSprite = &state->icons[1];
428 summon = SummonDefinition_Get(mode);
429 ability = BattleActGet(summon->nameMessageId);
430 handle = VramCache_AllocEntry(128);
431 commandWindow =
433 n = 0;
434 for (j = 0; j <= 3; j++) {
435 if (summon->djinnRequired[j] > state->standbyDjinn[commandIndex][j]) {
436 break;
437 }
438 }
439 ok = (j == 4);
440 state->icons[0].oam.f.x = 56;
441 iconSprite->oam.word.attr01 = 0x40000400;
442 iconSprite->oam.word.attr23 = 0;
443 /* FAKEMATCH(barrier): counted as 4 bytes, the empty asm puts the pool
444 * after mov r2, r9 as native (constant 56); without it, 34 of 1727
445 * instructions differ in tbs-en. */
446 __asm__ volatile("");
447 iconSprite->oam.f.x = commandWindow->x * 8 + 8;
448 iconSprite->oam.f.y = commandWindow->y * 8 + 4;
449 iconSprite->oam.f.tile = Resource_LoadIndexedEntryToBuffer(
450 summon->nameMessageId & 0x3fff, handle);
451 state->iconShown[1] = 1;
452 if (ok == 0) {
454 }
456 MsgAbilityName,
457 commandWindow, 16, 0);
458 for (j = 0; j <= 3; j++) {
459 if (summon->djinnRequired[j] != 0) {
460 UiWindow_SetTilemapEntry(commandWindow, j + 20481,
462 0);
463 UiWindow_PutGlyph(commandWindow, summon->djinnRequired[j] + 48,
464 n * 2 + BATTLE_SUMMON_COST_COLUMN, 0, 0);
465 n++;
466 }
467 }
468 if (ok != 0) {
470 } else {
472 }
474 actorId, ability->targetMode, ability->range,
475 Battle_ClassifyEntryKind((const struct BattleAct *)ability));
476 command->range = ability->range;
477 state->iconShown[1] = 0;
478 Resource_ResetEntry(handle);
479 UiWork_Finalize(commandWindow, 1);
480 if (mode == -1) {
481 goto djinn_menu;
482 }
483 for (j = 0; j <= 3; j++) {
484 if (summon->djinnRequired[j] > state->standbyDjinn[commandIndex][j]) {
485 state->standbyDjinn[commandIndex][j] = 0;
486 break;
487 }
488 state->standbyDjinn[commandIndex][j] -= summon->djinnRequired[j];
489 }
490 target = mode;
491 break;
492 }
493
494 case 15: {
495 struct BattleAct *ability;
496 struct UiWindow *hint;
497 s32 cost;
498 s32 element;
499 s32 index;
500
502 BATTLE_MENU_SET_CURSOR(0, 0, 0);
503 summon_menu:
504 state->icons[0].oam.f.x = 144;
505 gLinkCountdownWork->chosenDjinn[commandIndex] = 0x80000000;
506 mode = Battle_SelectAbility(actorId, 1);
507 command->range = 0;
508 if (mode == -1) {
509 goto mark_visible;
510 }
511 commandKind = 5;
512 parameter = mode;
513 gLinkCountdownWork->chosenDjinn[commandIndex] = mode;
514 element = (parameter >> 8) & 15;
515 index = parameter & 255;
516 if (Djinn_IsActiveFar(actorId, element, index) != 0) {
517 ability = BattleActGet(Djinn_GetAbilityIdFar(element, index));
518 cost = ability->range;
519 commandWindow = UiWindow_Create(11, 17, 10, 3, 6);
520 state->icons[0].oam.f.x = 64;
521 UiWindow_SetTilemapEntry(commandWindow, element + 20481, 0, 0, 0);
522 UiText_DrawCharacterAtOffset(element * 20 + index + MsgDjinnName,
523 commandWindow, 16, 0);
524 command->range = cost;
525 WaitFrames(1);
528 actorId, ability->targetMode, cost,
529 Battle_ClassifyEntryKind((const struct BattleAct *)ability));
530 if (state->tutorialStep != 0) {
531 hint =
532 UiText_ShowMessageAndWaitComplete(MsgDjinnUnleashHint, 15, 8);
533 while (UiWork_IsComplete() == 0) {
534 WaitFrames(1);
535 }
536 UiWork_Finalize(hint, 1);
537 state->tutorialStep++;
538 state->tutorialDelay = 45;
539 }
540 UiWork_Finalize(commandWindow, 1);
541 if (mode == -1) {
542 goto summon_menu;
543 }
544 target = mode;
545 break;
546 }
547 commandWindow = UiWindow_Create(11, 17, 10, 3, 6);
548 state->icons[0].oam.f.x = 64;
550 UiWindow_SetTilemapEntry(commandWindow, element + 20481, 0, 0, 0);
551 UiText_DrawCharacterAtOffset(element * 20 + index + MsgDjinnName,
552 commandWindow, 16, 0);
554 command->range = 1;
555 WaitFrames(1);
557 mode = BattleTarget_RunSelection(actorId, 4, 0, 7);
558 UiWork_Finalize(commandWindow, 1);
559 if (mode == -1) {
560 goto summon_menu;
561 }
562 target = mode;
563 break;
564 }
565
566 case 2: {
567 struct MenuSprite *iconSprite;
568 struct BattleAct *ability;
569 u16 *list;
570 u8 *pick;
571 s32 cost;
572 s32 handle;
573 s32 cnt;
574 s32 k;
575 s32 entryValue;
576 s32 selection;
577
579 mode = 0;
580 BATTLE_MENU_SET_CURSOR(mode, mode, mode);
581 item_menu:
582 state->icons[0].oam.f.x = 96;
583 pick = state->listSlots;
584 list = state->listAbilities;
585 cnt = 0;
586 k = 0;
587 entryValue = unit->inventory[k];
588 if (entryValue != 0) {
589 do {
590 Item_GetDirectFar(entryValue);
591 if (Item_ClassifyUseAbility(actorId, entryValue) == 0) {
592 list[cnt] = entryValue;
593 pick[cnt++] = k;
594 }
595 k++;
596 if (k == 15) {
597 break;
598 }
599 entryValue = unit->inventory[k];
600 } while (entryValue != 0);
601 }
602 k = 0;
603 entryValue = unit->inventory[k];
604 if (entryValue != 0) {
605 do {
606 Item_GetDirectFar(entryValue);
607 if (Item_ClassifyUseAbility(actorId, entryValue) != 0) {
608 list[cnt] = entryValue;
609 pick[cnt++] = k;
610 }
611 k++;
612 if (k == 15) {
613 break;
614 }
615 entryValue = unit->inventory[k];
616 } while (entryValue != 0);
617 }
618 list[cnt] = 0;
619 mode = ItemList_SelectEntry(actorId, list, cnt);
620 if (mode == -1) {
621 goto mark_visible;
622 }
623 selection = pick[mode];
624 parameter = selection;
625 ability = BattleActGet(
626 Item_GetDirectFar(unit->inventory[selection])->actionId);
627 cost = ability->range;
628 iconSprite = &state->icons[1];
629 handle = VramCache_AllocEntry(128);
630 commandWindow = UiWindow_Create(9, 17, BATTLE_ITEM_WINDOW_WIDTH, 3, 6);
631 state->icons[0].oam.f.x = 48;
632 iconSprite->oam.word.attr01 = 0x40000400;
633 iconSprite->oam.word.attr23 = 0;
634 /* FAKEMATCH(barrier): counted as 4 bytes, the empty asm puts the pool
635 * after ldr r1, [sp, #72] as native (constant 48); without it, 6 of
636 * 1727 instructions differ in tbs-en. */
637 __asm__ volatile("");
638 iconSprite->oam.f.x = commandWindow->x * 8 + 8;
639 iconSprite->oam.f.y = commandWindow->y * 8 + 4;
640 iconSprite->oam.f.tile =
641 ItemIcon_LoadIntoSlot(unit->inventory[selection], handle);
642 state->iconShown[1] = 1;
643 UiText_DrawCharacterAtOffset((unit->inventory[selection] & 0x1ff) +
644 MsgItemName,
645 commandWindow, 24, 0);
646 command->range = cost;
649 actorId, ability->targetMode, cost,
650 Battle_ClassifyEntryKind((const struct BattleAct *)ability));
651 state->iconShown[1] = 0;
652 Resource_ResetEntry(handle);
653 UiWork_Finalize(commandWindow, 1);
654 if (mode == -1) {
655 goto item_menu;
656 }
657 commandKind = 2;
658 target = mode;
659 break;
660 }
661
662 case 3:
663 commandKind = 3;
664 break;
665 }
666
668 command->unitId = (u16)actorId;
669 // Draw the priority random value once, only for a nonzero agility.
670 priority = unit->agi;
671 if (priority != 0) {
672 priority += (u32)(unit->agi * Random16()) >> 20;
673 }
674 command->priority = priority;
675 if (commandIndex != 0 &&
676 actors[commandIndex] == actors[commandIndex - 1]) {
677 command->priority = (s16)priority / 2;
678 }
679 if ((s16)command->priority < 0) {
680 command->priority = 2000;
681 }
682 command->command = commandKind;
683 command->parameter = parameter;
684 command->target = target;
685 commandIndex++;
686 if (commandIndex < commandCount) {
687 continue;
688 }
689 break;
690 }
691
692 if (commandIndex < commandCount) {
693 continue;
694 }
695 break;
696 }
697
698 // Publish completion, then wait for the peer to finish or disconnect.
699 if (state->linkTimer != 0) {
700 transferWords = (u16 *)gSerialTransfer.payload;
701 transferWords[4] = 'E';
702 transferWords[5] = 'D';
703 transferWords[6] = 'V';
704 transferWords[7] = 'S';
705 }
706 if (state->timerWindow != 0) {
707 UiWork_Finalize((struct UiWindow *)state->timerWindow, 1);
708 }
709 Resource_ResetEntry(smallIconSlot);
710 Resource_ResetEntry(largeIconSlot);
712 if (state->linkTimer != 0) {
713 // Keep the completion wait visible while the peer finishes its commands.
714 s32 Link_DrawWaitingForOpponent(void) {
715 u16 data[64];
716 BATTLE_MENU_MESSAGE_COPY(MsgWaitingForOpponent, data,
719 data, (struct UiWindow *)state->timerWindow, 0, 4);
720#ifdef UBFIX
721 return 0;
722#endif
723 }
724
725 linkBattle = gBattleWork;
726 mode = 0;
727 if (state->timerWindow == 0 && linkBattle->linkPaused == 0) {
728 state->timerWindow = (s32)UiWindow_Create(0, 16, 30, 4, 42);
730 Link_DrawWaitingForOpponent();
731 } else {
732 state->timerWindow = 0;
733 }
734 for (;;) {
735 peerSignature = (u16 *)&gLinkPeerSignatures[linkBattle->linkSide ^ 1];
736 if (linkBattle->linkPaused != 0) {
737 commandCount = -1;
738 break;
739 }
740 if ((gLinkStatus & 3) != 3) {
741 mode++;
742 if (mode > 24) {
743 commandCount = -1;
744 break;
745 }
746 } else {
747 mode = 0;
748 if (peerSignature[4] == 'E' && peerSignature[5] == 'D' &&
749 peerSignature[6] == 'V' && peerSignature[7] == 'S') {
750 break;
751 }
752 if (!(peerSignature[4] == 'V' && peerSignature[5] == 'S' &&
753 peerSignature[6] == 'S' && peerSignature[7] == 'T')) {
754 mode = 1;
755 }
756 }
757 WaitFrames(1);
758 }
759 if (state->timerWindow != 0) {
760 UiWork_Finalize((struct UiWindow *)state->timerWindow, 1);
761 }
762 }
765 return commandCount;
766}
What every part of the menu object shares: its includes, edition values, macros and the link round st...
#define BATTLE_CLASS_ICON_X
#define BATTLE_MENU_MESSAGE_COPY
#define PSYNERGY_COST_SECOND_TILE
#define BATTLE_SUMMON_COST_COLUMN
#define BATTLE_SUMMON_ICON_X
#define BATTLE_ITEM_WINDOW_WIDTH
#define BATTLE_COMMAND_NAME_X
#define BATTLE_SUMMON_WINDOW_WIDTH
#define BATTLE_SUMMON_ELEMENT_COLUMN
#define BATTLE_MENU_MESSAGE_CAPACITY
@ ABILITY_KIND_HEAL_PP
Ember, Psy Crystal, Adept Ring.
Definition battle_unit.h:70
@ ABILITY_KIND_HEAL_HP
Cure, Fizz, healing items.
Definition battle_unit.h:62
@ ABILITY_EFFECT_CURE_ALL
Tonic.
@ ABILITY_EFFECT_RESTORE
Restore, Elixir.
Definition battle_unit.h:80
@ ABILITY_EFFECT_CURE_POISON
Cure Poison, Antidote.
Definition battle_unit.h:79
#define ABILITY_KIND_MASK
The low four bits of BattleAct.flags: how BattleTargetExec applies the ability's power.
Definition battle_unit.h:52
struct BattleWork * gBattleWork
s32 Menu_RunCommandRow(s32 mode)
Selects a command icon, returning its kind, -1 for cancel or -2 for a shoulder-button switch.
Definition command_row.c:28
struct UiWindow * UiText_ShowMessageAndWaitComplete(s32 message, s32 x, s32 y)
Opens a message at (x, y), waits for its text to finish, and returns its window so the caller can hol...
Definition command_row.c:9
s32 BattleLayout_HighlightPartyPanels(u16 *ids)
Dims the party strip, then highlight the actor IDs up to the 0xff terminator.
s32 Battle_SelectAbility(s32 owner, s32 unused)
Selects a Djinni for the current battle command.
Definition djinn_menu.c:28
s32 BattleParty_ListActorIdsFar(s32 groups, u16 *dst)
void BattlePres_SetActorModesFar(u16 *actors, s32 mode)
s32 BattleParty_CountStandbyDjinnFar(u32 unitId, u8 *counts)
void Camera_ConfigureSceneFar(s32 pos)
struct BattleUnit * UnitGetFar(u32 owner)
struct ItemDefinition * Item_GetDirectFar(s32 item)
s32 GameFlag_TestFar(s32 flag)
struct BattleAct * BattleActGet(s32 actionId)
Far call to BattleAction_GetDirect.
u32 Djinn_IsActiveFar(s32 owner, s32 index, s32 bit)
const struct SummonDefinition * SummonDefinition_Get(u32 summon_id)
Far call to SummonDefinition_GetNear.
s32 Djinn_GetAbilityIdFar(u32 group, u32 index)
s32 Battle_IsReviveEffectFar(s32 effect_id)
void AudioCommand_PlayFar(s32 id)
#define FLAG_DJINN_TUTORIAL
Definition flags.h:69
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
u8 gDebugMode
Debug builds: Start+Select pauses the frame loop.
s32 UiWork_IsComplete(void)
Returns 1 when every message channel has finished its text (or is idle), and 0 while one is still typ...
Definition frames.c:210
u16 gLinkPeerSignatures[][12]
24 bytes per peer
void UiText_RenderWideStringAtOffset(u16 *text, struct UiWindow *window, s32 x, s32 y)
Draws a zero-terminated string of 16-bit character codes into a text canvas window at pixel (x,...
Definition glyphs.c:258
void * MemAlloc(s32 size)
Allocates size bytes (rounded up to words) with no slot, from IWRAM when they fit and EWRAM otherwise...
Definition heap.c:115
void * Runtime_AllocateBlock(s32 kind, s32 size)
As Runtime_AllocateHeapBlock, but tries EWRAM first, for blocks that need room more than speed: the b...
Definition heap.c:80
@ KEY_START
Definition io_reg.h:246
s32 Item_ClassifyUseAbility(s32 unit, s32 item)
Checks whether an item can be used in battle.
Definition item_menu.c:11
s32 ItemList_SelectEntry(s32 owner, u16 *entries, s32 count)
Chooses an inventory-list position for battle use, or -1 on cancel.
Definition item_menu.c:46
volatile u32 gKeysHeld
Keys down now.
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
void Runtime_ReleaseHeapBlock(s32 slot)
void MemFree(void *buffer)
struct BattleMenuWork * gLinkCountdownWork
#define BATTLE_MENU_SET_CURSOR(page_, row_, preferred_)
Saves the selection: page, row and return row.
Definition menu_list.h:183
s32 Battle_ClassifyEntryKind(const struct BattleAct *act)
Returns the target selection category for an ability's effect.
s32 Battle_CollectPartyCommands(struct BattleActionRecord *commands, u16 *actors, s32 commandCount)
Collects commands in party order, including target, cost and randomized priority.
s32 Resource_LoadIndexedIntoBuffer(s32 slotIndex, s32 icon)
Decodes a command-icon table entry in temporary transfer work and reload the requested cache slot.
Definition pictures.c:401
s32 Resource_LoadIndexedEntryToBuffer(s32 resource, s32 index)
Builds the ability glyph in temporary transfer work, reloads the requested cache slot and returns its...
Definition pictures.c:325
void Link_DrawShiftedTilePair(s32 offset)
Animates the two link indicator tiles with opposing two/three-pixel shifts.
Definition pictures.c:237
s32 ItemIcon_LoadIntoSlot(s32 resource, s32 index)
Composes the item icon with style 0x1a in temporary transfer work and reload the requested cache slot...
Definition pictures.c:312
s32 UiGlyph_LoadPortrait(u32 member, s32 cacheSlot)
Loads a party portrait into the supplied cache slot and returns its tile.
Definition pictures.c:341
void Graphics_ExpandVramTilesByColorTable(u16 *dst)
Expands two palette variants of the ten source tile rows at 0x06000600, mapping each packed nibble th...
Definition pictures.c:256
s32 Menu_BuildLocalizedPatternTiles(void)
Definition pictures.c:137
s32 BattleMenu_RunActionSelection(s32 unitId, u16 *actions, s32 count)
Selects a Psynergy-list position, or -1 on cancel.
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
Definition scheduler.c:102
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
volatile u16 gLinkStatus
Link status, updated by the VBlank exchange handler.
struct SerialTransferState gSerialTransfer
#define SE_CAST
Definition songs.h:149
#define SE_MENU_ERROR
Definition songs.h:107
#define SE_MENU_CONFIRM
Definition songs.h:105
#define SE_110
Definition songs.h:103
An ability's definition, a row of gBattleAction_DefinitionTable: its targeting, kind,...
u8 ppCost
PP the ability costs.
u8 effect
enum AbilityEffect
u8 range
the aimed unit and range - 1 either side, or ABILITY_RANGE_ALL
u8 element
enum Element
u8 targetMode
TARGET_MODE_NONE, _FOES, _ALLIES or _SELF.
u8 flags
bits: 7 usable in battle | 6 usable in the field | 5..4 clear in every row | 3..0 kind (ABILITY_KIND_...
A unit's chosen action for the turn: its command, the command's parameter, its target and range,...
s16 target
the aimed unit's id
s16 parameter
an ability id, or CMD_ITEM's inventory index (-1 gone)
s16 command
enum BattleCommand
s16 range
the action's range
u16 priority
from the unit's Agility; higher acts first
The battle command menus' work, heap slot 57 (0x104 bytes), reached as gLinkCountdownWork.
Definition menu_list.h:107
s32 tutorialDelay
frames until the tutorial's next key press
Definition menu_list.h:142
s32 commandActor
The member whose commands are being chosen; -1 between members.
Definition menu_list.h:144
u8 listSlots[34]
the Psynergy list's action slots, ended by 0
Definition menu_list.h:136
s32 linkTimer
1 while the link battle's timer runs
Definition menu_list.h:132
s32 timerWindow
The window that shows the link battle's seconds left, a struct UiWindow pointer kept as a word (as a ...
Definition menu_list.h:126
s32 timerHidden
Set while the status screen is open, so the timer opens no window.
Definition menu_list.h:128
u16 listAbilities[33]
the Psynergy list's ability ids, ended by 0
Definition menu_list.h:137
s32 sceneOffset
where the slide has reached; a third of the way a frame
Definition menu_list.h:116
s32 timer
Frames left to choose commands in a link battle; -1 outside link battles.
Definition menu_list.h:131
u8 iconShown[3]
whether each of icons is drawn
Definition menu_list.h:111
u8 standbyDjinn[8][4]
The party's standby Djinn by element before each command: what the summons chosen by the earlier comm...
Definition menu_list.h:135
s32 targetSceneOffset
Where the battle scene slides to (Camera_ConfigureScene's vertical offset): -2 or 16 by the target me...
Definition menu_list.h:115
s32 commandSelection[2]
The command row's choice: [0] for the party's row (fight, flee, status), [1] for a member's commands.
Definition menu_list.h:122
s32 tutorialStep
The Djinn tutorial's step: 0 off, 1 from the start of each round while FLAG_DJINN_TUTORIAL is set,...
Definition menu_list.h:141
u32 chosenDjinn[8]
The Djinni each command has chosen, element << 8 | index, or 0x80000000.
Definition menu_list.h:146
struct MenuSprite icons[3]
The sprites UpdateLinkSessionCountdown draws each frame: the chosen command's icon,...
Definition menu_list.h:110
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 psySeal
bits: 7..3 Luff (16 when cast, minus 8 a turn) | 2..0 Bind's turns (7 when cast).
s16 pp
current PP
struct OwnerActionSlot actionSlots[32]
The action list: Psynergy taught for good, then the class's and the equipment's (Unit_RefreshPsynergy...
u8 classId
Who the unit is: a character's id (ISAAC to JENNA, below 8) or an enemy's id (BattleUnitSet).
u16 agi
Agility, 0 to 999: the order of the round's actions.
u16 inventory[15]
Items held, one entry each: bits 15..11 quantity | 10 broken | 9 equipped | 8..0 item id (INVENTORY_*...
The battle's own work: its enemies, units and their objects, the turn's actions, the spoils,...
Definition battle_work.h:71
u8 twoSided
1 in a link battle
Definition battle_work.h:90
u8 linkPaused
set when the link drops or the console's id changes
u8 linkSide
this console's multiplayer id
Definition battle_work.h:98
u16 actionId
the ability used, or taught as Psynergy
Definition item.h:120
A menu sprite: a list link and its OAM attributes, as two words or as fields.
Definition menu_list.h:24
union MenuSprite::@002225022013150231017316170057321303227123371224 oam
u16 encodedAction
bits: 15 from the class | 14 from an equipped item | 13..0 action id.
Definition battle_unit.h:22
u8 payload[20]
one block of the data sent
A summon: its name's message and the Djinn of each element it needs.
u16 nameMessageId
The summon's ability id: its name is message MsgAbilityName plus it, and its low 14 bits pick the ico...
u8 djinnRequired[4]
standby Djinn needed, by element
The window system's work: the windows' tilemap, the windows, the three text channels,...
Definition window.h:19
u8 mode
Set while Mind Read shows thoughts: round frame corners, colour 8 text with no shadow,...
Definition window.h:35
u8 level
text tiles' palette; 15 by default, 14 or 5 for low HP
Definition window.h:41
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
u16 y
tiles
Definition uiwindow.h:16
u16 state
0 while a message channel is typing into the window; 1 once its text has ended or closed the window,...
Definition uiwindow.h:24
u16 x
tiles
Definition uiwindow.h:15
s32 SummonMenu_SelectSummon(s32 unused0, s32 unused1, const u8 *standby)
Shows learned summons four per page; returns the selected summon number.
Definition summon_menu.c:18
void UiText_DrawNumberAtOffset(s32 value, s32 width, const struct UiWindow *window, s32 x, s32 y)
Draws a number (width as UiText_FormatNumber) as tiles in a window at pixel (x, y) of its interior.
Definition text_tiles.c:668
void UiWindow_MarkVisibleTileAttributes(void)
Marks the text tiles the tilemap shows, and frees those it no longer shows.
Definition text_tiles.c:299
void UiWork_SetParamNibble(s32 param)
Sets the text colour (0 to 15) of drawn text.
Definition text_tiles.c:524
void UiText_DrawCharacterAtOffset(s32 message, const struct UiWindow *window, u32 offsetX, u32 offsetY)
Decodes a message and draws it as tiles in a window at pixel (offsetX, offsetY) of its interior.
Definition text_tiles.c:552
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed char s8
Definition types.h:10
signed long long s64
Definition types.h:16
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
#define ACTION_ID_MASK
Definition window.h:269
#define UI_WORK
Definition window.h:267
s32 VramCache_AllocEntry(s32 size)
Takes a free cache entry, gives it size bytes of sprite VRAM and returns its number.
Definition vram_cache.c:227
s32 Resource_ResetEntry(u32 no)
Frees cache entry no: its blocks go back and the entry is marked free (offset 0xffff).
Definition vram_cache.c:106
s32 Ui_RunOwnerStatusScreen(u16 *list, s32 listCount, s32 owner)
Shows a party member's stats and condition help until B or the link session ends.
Definition status.c:41
s32 BattleTarget_RunSelection(s32 selection, s32 mode, u32 spread, u32 kind)
Chooses a party/enemy target and animates its selection markers.
Definition targets.c:27
void UiWindow_PutGlyph(struct UiWindow *win, u32 tile, u32 x, u32 y, s32 mode)
Puts a character into a window's tilemap as a tile at tile (x, y) of its interior.
Definition sprites.c:187
void UiWindow_SetTilemapEntry(struct UiWindow *window, s32 value, s32 x, s32 y, u32 mode)
Writes value into a window's tilemap at tile (x, y) of its interior, with the palette mode names (TIL...
Definition sprites.c:345
s32 Ui_FillVramBlockPattern(void)
Fills the text canvas with the window background colour (4).
Definition windows.c:619
void UiWork_Finalize(struct UiWindow *window, s32 instant)
Closes a window: clears its contents and remembers its last rectangle.
Definition windows.c:349
struct UiWindow * UiWindow_Create(s32 x, s32 y, s32 width, s32 height, s32 attrs)
Opens a window at tile (x, y) of width by height tiles in the first free window slot,...
Definition windows.c:279