Alchemy
Loading...
Searching...
No Matches

selection.c

Go to the documentation of this file.
1/// @file
2/// The selection screen's row of icons, and the field menu.
3/// Part of window.c, the window object, compiled only through it.
4
6
7/// Two halfwords of a selection record, the second cleared as its cursor.
8struct GlyphCursor {
11};
12
13static __inline__ void ResetCursor(struct GlyphCursor *cursor) {
14 /* FAKEMATCH: the helper takes the node's base field, so each row store forms
15 * base + 372 and stores at #2; as work->records[7].kind = 0, 6 instructions
16 * differ in tbs-en. */
17 cursor->cursor = 0;
18}
19
20/// Allocates and resets the selection screen: the row of icons the player picks
21/// from, with arrows at each end and a pointing hand over the chosen target.
23 struct SelectionScreen *work;
24 struct SelectionSprite *visual;
25 const u8 *table;
26 s32 i;
27 u16 clear = 0;
28
29 work = Runtime_AllocateBlock(18, sizeof(struct SelectionScreen));
30 work->head = NULL;
31 work->path = NULL;
32 work->window = NULL;
33 work->unk39a = clear;
34 work->top = clear;
35 work->cursorIndex = 128;
36 work->verticalScroll = 32;
37 work->count = clear;
38 work->locked = 999;
39 i = 0;
40 do {
41 work->records[i + 2].kind = 0;
42 work->records[i + 9].kind = 0;
43 i++;
44 } while (i != 5);
45 ResetCursor((struct GlyphCursor *)&work->records[7].base);
46 ResetCursor((struct GlyphCursor *)&work->records[8].base);
47 work->records[0].kind = 0;
48 work->records[1].kind = 0;
49 work->records[0].y = 0;
50 work->records[1].y = 0;
53 work->records[14].tile = VramCache_Load(work->records[14].slot, 256, table);
54 work->records[14].kind = 0;
55 work->records[14].scale = 0;
56 work->records[15].kind = 0;
57 visual = &work->records[14].sprite;
58 visual->mode = 0;
59 visual->mosaic = 0;
60 visual->colors = 1;
61 visual->affine = 0;
62 visual->param = 0;
63 visual->size = 1;
64 visual->shape = 0;
65 visual->priority = 0;
66}
67
68/// Empties the selection screen's list of entries.
69/// The high cursor bit requests resetting both the list origin and cursor.
71 struct SelectionScreen *screen;
72
73 screen = gResQueueWork;
74 screen->head = NULL;
75 screen->unk39a = 0;
76 if (screen->cursorIndex & 0x80) {
77 screen->top = 0;
78 screen->cursorIndex = 0;
79 }
80 screen->verticalScroll = 0;
81 screen->count = 0;
82}
83
84/// Adds an entry (kind and id) to the selection screen's list, up to 16.
85/// The count starts at 0 when the screen is created or cleared.
87 struct SelectionScreen *state = gResQueueWork;
88 u16 entryCount = state->count;
89
90 if (entryCount != UI_SELECTION_ENTRY_LIMIT) {
91 state->kinds[entryCount] = kind;
92 state->bases[entryCount] = base;
93 state->count++;
94 }
95}
96
97/// Creates icons for the first five listed entries in a row along the bottom of
98/// the screen.
99/// Builds the linked row before placing the visible icons and loading the
100/// preview.
102 struct SelectionScreen *screen = gResQueueWork;
103 u32 count = screen->count;
104 u32 entryIndex = screen->top;
105 struct SelectionNode *previous = 0;
106 struct SelectionNode *node;
107 s32 rowPosition = 0;
108
109 while (entryIndex < count) {
110 s32 base = screen->bases[entryIndex];
111 u32 kind = screen->kinds[entryIndex];
112
114 if (node == 0)
115 break;
117 if (screen->head == 0) {
118 screen->head = node;
119 node->prev = 0;
120 } else {
121 previous->next = node;
122 node->prev = previous;
123 }
124 node->next = 0;
125 rowPosition++;
126 previous = node;
127 if (rowPosition == 5)
128 break;
129 entryIndex++;
130 }
131
132 screen->baseX = 100 - rowPosition * 8;
133 screen->baseY = 140;
134 // Reuse the count as a pixel offset while placing the completed row.
135 // Separate count/offset locals change the native English object.
136 for (previous = screen->head, rowPosition = 0; previous != 0;
137 previous = previous->next) {
138 s32 x = screen->baseX + rowPosition;
139 s32 y;
140
141 previous->x = x;
142 y = screen->baseY;
143 previous->y = y;
144 previous->targetX = x;
145 previous->targetY = y;
146 if (previous->kind == 6 && screen->locked == 0) {
147 previous->y = 6;
148 previous->targetY = 6;
149 }
150 previous->dx = 0;
151 previous->dy = 0;
152 rowPosition += 16;
153 }
155}
156
158
159/// Returns a free selection icon record: one of the seven row icons (kind 0) or
160/// of the five chosen icons (otherwise), or NULL.
162 struct SelectionScreen *state = gResQueueWork;
163 s32 i;
164
165 if (kind != 0) {
166 for (i = 0; i != 5; i++) {
167 if (state->records[i + 9].kind == 0)
168 return &state->records[i + 9];
169 }
170 } else {
171 for (i = 0; i != 7; i++) {
172 if (state->records[i + 2].kind == 0)
173 return &state->records[i + 2];
174 }
175 }
176 return NULL;
177}
178
179/// Starts drawing the selection screen each frame.
182}
183
184/// Stops drawing the selection screen.
187}
188
189/// The selection screen's per-frame callback: slides and draws the row of
190/// icons, the large icon over the chosen one, the end arrows, the icons already
191/// chosen and the pointing hand.
193 struct SelectionScreen *state = gResQueueWork;
194 struct SelectionSprite *cursorEntry = &state->records[14].sprite;
195 struct SelectionNode *cursor = &state->records[14];
196 struct SelectionNode *transfer = &state->records[15];
197 struct SelectionNode *node;
198 struct SelectionSprite *sprite;
199 struct SelectionSprite *commandSprite;
200 s32 entryIndex = 0;
201 s32 slot;
202 s32 axisStep;
203 struct EffectPosition pos;
204
205 node = state->head;
206 // Move and queue the visible row before drawing its overlays.
207 while (node != 0) {
208 sprite = &node->sprite;
209 sprite->affine = 0;
210 sprite->param = 0;
211 sprite->x = node->x;
212 sprite->y = node->y;
213 slot = 240;
214 if (state->verticalScroll != 0) {
215 sprite->y += state->verticalScroll;
216 } else if (node->x != node->targetX) {
217 if (node->dx > 0) {
218 if (node->x + node->dx > node->targetX) {
219 node->x = node->targetX;
220 } else {
221 node->x += node->dx;
222 }
223 } else {
224 if (node->x + node->dx < node->targetX) {
225 node->x = node->targetX;
226 } else {
227 node->x += node->dx;
228 }
229 }
230 sprite->x = node->x;
231 } else if (entryIndex == state->cursorIndex) {
232 slot = 241;
233 if (cursor->kind != 0) {
235 node->base, EffectPosition_Coordinates(&pos)) != -1) {
236 cursor->targetX = pos.x;
237 cursor->targetY = pos.y;
238 if (cursor->scale == 0) {
239 cursor->x = pos.x;
240 cursor->y = pos.y;
241 cursor->scale = 1;
242 }
243 }
244 }
245 }
246 if (node->scale != 0) {
248 if (state->records[14].kind == 1) {
249 sprite->mode = 1;
250 } else {
251 sprite->mode = 0;
252 }
253 if (node->kind == 1) {
254 sprite->mode = 1;
255 }
256 }
257 Runtime_PushSlotEntry(sprite, slot);
258 }
259 node = node->next;
260 entryIndex++;
261 }
262 // The selected command's large icon owns a separate cached tile block.
263 if (transfer->kind != 0) {
264 node = Selection_GetCursorNode(state);
265 commandSprite = &transfer->sprite;
266 commandSprite->mode = 0;
267 commandSprite->affine = 0;
268 commandSprite->param = 0;
269 commandSprite->mosaic = 0;
270 commandSprite->colors = 1;
271 commandSprite->size = 2;
272 commandSprite->shape = 0;
273 commandSprite->priority = 0;
274 commandSprite->tile = transfer->tile;
275 commandSprite->x = node->x - 4;
276 commandSprite->y =
277 node->y + (gMenu_CursorBobOffsets[(gFrameTick >> 1) & 15] >> 1) - 4;
278 if (transfer->scale != transfer->scaleEnd) {
279 state->transform.scaleX = transfer->scale;
280 state->transform.scaleY = transfer->scale;
281 state->transform.angle = 0;
282 commandSprite->param = AffineMatrix_BuildForEffect(&state->transform);
283 commandSprite->affine = 3;
284 commandSprite->x += 0xfff0;
285 commandSprite->y += 0xf0;
286 transfer->scale += transfer->scaleStep;
287 }
289 commandSprite->mode = 1;
290 }
291 Runtime_PushSlotEntry(commandSprite, 248);
292 }
295 // Chosen entries gather at the top-left independently of the scrolling row.
296 node = state->path;
297 while (node != 0) {
298 sprite = &node->sprite;
299 if (node->x != node->targetX) {
300 node->x += node->dx;
301 }
302 if (node->y != node->targetY) {
303 node->y += node->dy;
304 }
305 sprite->x = node->x;
306 sprite->y = node->y;
307 if (node->scale != node->scaleEnd) {
308 node->scale += node->scaleStep;
309 state->transform.scaleX = node->scale;
310 state->transform.scaleY = node->scale;
311 state->transform.angle = 0;
313 sprite->affine = 3;
314 sprite->x += 0xfff8;
315 sprite->y += 0xf8;
316 } else {
317 sprite->affine = 0;
318 sprite->param = 0;
319 }
321 if (state->records[14].kind == 1) {
322 sprite->mode = 1;
323 } else {
324 sprite->mode = 0;
325 }
326 if (node->kind == 1) {
327 sprite->mode = 1;
328 }
329 }
330 Runtime_PushSlotEntry(sprite, 240);
331 node = node->next;
332 }
333 // Point at the selected battle target, smoothing each axis separately.
334 if (cursor->kind != 0) {
335 entryIndex = (s32)gMenu_AnimatedCursorTiles;
336 {
337 void *src = (void *)(entryIndex + (((gFrameTick >> 2) & 15) << 8));
338
339 cursorEntry->tile = VramCache_Load(cursor->slot, 0x100, src);
340 }
341 if (cursor->targetX != cursor->x) {
342 axisStep = (cursor->targetX - cursor->x) >> 1;
343 if (axisStep != 0) {
344 cursor->x += axisStep;
345 } else {
346 cursor->x = cursor->targetX;
347 }
348 }
349 if (cursor->targetY != cursor->y) {
350 if ((axisStep = (cursor->targetY - cursor->y) >> 1) != 0) {
351 cursor->y += axisStep;
352 } else {
353 cursor->y = cursor->targetY;
354 }
355 }
356 cursorEntry->y =
357 cursor->y + gMenu_CursorBobOffsets[(gFrameTick >> 2) & 15] - 32;
358 cursorEntry->x = cursor->x - 4;
360 if (state->records[14].kind == 1) {
361 cursorEntry->mode = 1;
362 } else {
363 cursorEntry->mode = 0;
364 }
365 }
366 Runtime_PushSlotEntry(cursorEntry, 248);
367 }
368 state->status += 1;
369}
370
371/// Draws the selection screen's left (index 0) or right (1) arrow, nudged
372/// outwards while it flashes after a scroll.
374 u32 animationStep = (gFrameTick >> 2) & 7;
375 struct SelectionSprite *arrow;
376 const u8 *arrowTiles;
377 const u8 *tmp;
378
379 if (state->records[side].kind == 0)
380 return;
381 arrow = &state->records[side].sprite;
382 arrow->x = state->records[side].x;
383 arrow->y = state->records[side].y;
384 if (side != 0) {
385 arrowTiles = gMenu_CursorObjectTiles;
386 if (state->records[1].base != 0)
387 arrow->x = arrow->x + state->records[1].base;
388 } else {
389 arrowTiles = gMenu_CursorLeftObjectTiles;
390 if (state->records[0].base != 0)
391 arrow->x = arrow->x - state->records[0].base;
392 }
393 tmp = arrowTiles + animationStep * 128;
394 arrow->tile = VramCache_Load(state->records[side].slot, 128, tmp);
396 if (state->records[14].kind == 1)
397 arrow->mode = 1;
398 else
399 arrow->mode = 0;
400 }
401 Runtime_PushSlotEntry(arrow, 238);
402 if (state->records[side].base != 0)
403 state->records[side].base--;
404}
405
406/// Opens or refits the name window above the selection row and writes the name
407/// of the icon under the cursor, or that nothing is known (mode 4, Psynergy)
408/// or held (mode 2, items). mode 6 is a yes or no question, placed at the
409/// bottom or top of the screen.
411 struct SelectionScreen *screen;
412 struct SelectionNode *node;
413 struct UiWindow **slot;
414 struct UiWindow *window;
415
416 screen = gResQueueWork;
417 node = Selection_GetCursorNode(screen);
418 slot = &screen->window;
419 window = *slot;
420 if (window == 0) {
421 if (mode == 6) {
422 if (screen->locked != 0) {
423 *slot = UiWindow_Create(17, 17, 5, 3, mode);
424 } else {
425 *slot = UiWindow_Create(17, 0, 5, 3, mode);
426 }
427 screen->verticalScroll = 0;
428 screen->locked = 999;
429 } else {
430 *slot = UiWindow_Create(19 + ((9 - count) >> 1), 17, count + 2, 3, 6);
431 }
433 } else {
434 if (count != 0 && window->width != count + 2) {
435 UiWork_Finalize(window, 2);
436 *slot = UiWindow_Create(19 + ((9 - count) >> 1), 17, count + 2, 3, 6);
437 }
439 }
440 if (screen->count != 0) {
441 UiText_DrawCharacterAtOffset(node->message, screen->window, 0, 0);
442 } else {
443 switch (mode) {
444 case 4:
445 UiText_DrawCharacterAtOffset(MsgAbilityNotKnown, screen->window, 0, 0);
446 break;
447 case 2:
448 UiText_DrawCharacterAtOffset(MsgItemNotHeld, screen->window, 0, 0);
449 break;
450 }
451 }
452}
453
454/// Closes the selection screen and frees its icons, tiles and work block.
456 struct SelectionScreen *state = gResQueueWork;
457 struct SelectionNode *node;
458
460 UiWork_Finalize(state->window, 2);
461 WaitFrames(1);
462 node = state->head;
463 while (node != 0) {
464 if (node->kind != 0) {
466 node->kind = 0;
467 }
468 node = node->next;
469 }
470 node = state->path;
471 while (node != 0) {
472 if (node->kind != 0) {
474 node->kind = 0;
475 }
476 node = node->next;
477 }
479 if (state->records[0].y != 0) {
481 if (state->records[0].y != 0) {
483 }
484 }
485 Resource_ResetEntry(state->records[14].slot);
487}
488
489/// Moves the row of icons to start at pixel (x, y), 16 pixels apart.
491 struct SelectionScreen *screen = gResQueueWork;
492 struct SelectionNode *node;
493
494 screen->baseX = x;
495 screen->baseY = y;
496 node = screen->head;
497 while (node != 0) {
498 node->x = x;
499 node->targetX = x;
500 node->y = y;
501 node->targetY = y;
502 node = node->next;
503 x += 16;
504 }
505}
506
507/// Sets up both end arrows of the selection row.
509 struct SelectionScreen *state;
510
511 state = gResQueueWork;
514}
515
516/// Sets up the left (index 0) or right (1) arrow of the selection row, shown
517/// when there are entries beyond that end.
519 struct SelectionSprite *arrow = &state->records[side].sprite;
520 const u8 *arrowTiles = 0;
521 u32 count;
522
523 state->records[side].kind = 0;
524 if (side != 0) {
525 /* FAKEMATCH(temporary): the tile pointer in a local, loaded early into r5;
526 * as gMenu_CursorObjectTiles where right is read, 35 of 136 instructions
527 * differ in tbs-en. */
528 const u8 *right = gMenu_CursorObjectTiles;
529
530 count = state->count;
531 if (state->top != 0)
532 count -= state->top;
533 if (count > 5) {
534 state->records[side].kind = 1;
535 count = 5;
536 }
537 arrowTiles = right;
538 state->records[1].x = state->baseX + 16 * (count - 1) + 17;
539 } else {
540 arrowTiles = gMenu_CursorLeftObjectTiles;
541 state->records[0].x = state->baseX - 9;
542 if (state->top != 0)
543 state->records[0].kind = 1;
544 }
545 if (state->records[side].y == 0) {
546 state->records[side].slot = Resource_FindFreeEntry();
547 state->records[side].tile =
548 VramCache_Load(state->records[side].slot, 128, arrowTiles);
549 state->records[side].y = state->baseY;
550 state->records[side].base = 0;
551 arrow->mode = 0;
552 arrow->mosaic = 0;
553 arrow->colors = 1;
554 arrow->affine = 0;
555 arrow->param = 0;
556 arrow->size = 0;
557 arrow->shape = 2;
558 arrow->priority = 0;
559 }
560}
561
562/// Returns the node at the selection screen's cursor index.
563/// cursorIndex is relative to head, not the number of queued entries.
565 struct SelectionNode *node = screen->head;
566 s32 i;
567
568 for (i = 0; i != screen->cursorIndex; ++i) {
569 node = node->next;
570 }
571 return node;
572}
573
574#define SELECTION_FIXED 999
575
576#define NODE_STATUS_SCROLLING 33
577#define NODE_STATUS_SHOWN 1
578
579#define NODE_KIND_YES_NO 6
580
581#define SELECTION_ROWS 4
582#define ARROW_SCROLL_FRAMES 8
583
584/// Runs the selection row until the player chooses (the chosen entry's index)
585/// or, when mode allows it, cancels with B (-1). SELECTION_FIXED allows no
586/// moving or choosing.
588 struct SelectionScreen *screen = gResQueueWork;
589
591 for (;;) {
592 WaitFrames(1);
593 if (screen->verticalScroll != 0) {
594 continue;
595 }
596 if (mode != SELECTION_FIXED) {
597 if (gKeysRepeat & KEY_RIGHT) {
598 Menu_StepRight(screen);
599 } else if (gKeysRepeat & KEY_LEFT) {
600 Menu_StepLeft(screen);
601 } else if (gKeysPressed & KEY_A) {
602 return Menu_ConfirmSelection(screen);
603 }
604 }
605 if (mode != 0 && (gKeysPressed & KEY_B)) {
606 return -1;
607 }
608 }
609}
610
611/// As Menu_SelectionLoop, with the menu sounds.
613 struct SelectionScreen *screen = gResQueueWork;
614 u32 result;
615
616 for (;;) {
617 WaitFrames(1);
618 if (screen->verticalScroll != 0) {
619 continue;
620 }
621
622 if (mode != SELECTION_FIXED) {
623 if (gKeysRepeat & KEY_RIGHT) {
625 Menu_StepRight(screen);
626 } else if (gKeysRepeat & KEY_LEFT) {
628 Menu_StepLeft(screen);
629 }
630
631 if (gKeysPressed & KEY_A) {
632 result = screen->top + screen->cursorIndex;
633 if (screen->head->kind == NODE_KIND_YES_NO) {
634 if (result == 0)
636 else
638 } else {
640 }
641 return result;
642 }
643 }
644
645 if (mode != 0 && (gKeysPressed & KEY_B)) {
647 return -1;
648 }
649 }
650}
651
652/// Moves the cursor one entry right, scrolling the row at its fourth place.
653/// This variant stops at the end; Menu_StepRight also wraps around.
654/// Nothing calls it.
656 u32 nextEntry = screen->top + screen->cursorIndex + 1;
657
658 if (nextEntry == screen->count) {
659 return;
660 }
663 WaitFrames(1);
664 screen->cursorIndex++;
665 if (screen->cursorIndex == SELECTION_ROWS && nextEntry + 1 < screen->count) {
666 screen->cursorIndex--;
667 screen->records[1].base = ARROW_SCROLL_FRAMES;
668 screen->top++;
670 if (screen->top + screen->cursorIndex + 2 == screen->count) {
671 screen->records[1].kind = FALSE;
672 }
673 screen->records[0].kind = TRUE;
674 }
675 screen->status = NODE_STATUS_SHOWN;
677 WaitFrames(1);
679 WaitFrames(1);
680}
681
682/// Moves the cursor one entry left, scrolling the row at its second place.
683/// This variant stops at the beginning; Menu_StepLeft also wraps around.
684/// Nothing calls it.
687
688 if (screen->top == 0 && screen->cursorIndex == 0) {
689 return;
690 }
693 WaitFrames(1);
694 cursorIndex = screen->cursorIndex;
695 if (cursorIndex == 1 && screen->top != 0) {
696 screen->records[0].base = ARROW_SCROLL_FRAMES;
697 screen->top--;
699 if (screen->top == 0) {
700 screen->records[0].kind = FALSE;
701 }
702 screen->records[1].kind = cursorIndex;
703 } else {
704 screen->cursorIndex--;
705 }
706 screen->status = NODE_STATUS_SHOWN;
708 WaitFrames(1);
710 WaitFrames(1);
711}
712
713/// Moves the cursor one entry right, scrolling the row at its edge and
714/// wrapping from the last entry to the first.
715void Menu_StepRight(struct SelectionScreen *state) {
716 struct SelectionNode *node;
717 u32 entryIndex;
718 s32 y;
719 u32 end;
720
723 WaitFrames(1);
724 state->cursorIndex++;
725 if (state->count > 5) {
726 end = state->top + state->cursorIndex;
727 if (end == state->count) {
728 node = state->head;
729 state->records[0].kind = 0;
730 while (node->next != NULL) {
731 node->targetX = state->baseX;
732 node->targetY = state->baseY;
733 node->dx = -12;
734 node = node->next;
735 }
736 node->targetX = state->baseX;
737 node->targetY = state->baseY;
738 node->dx = -12;
739 while (node->targetX != node->x)
740 WaitFrames(1);
741 node = state->head;
742 if (node != NULL) {
743 entryIndex = 0;
744 do {
745 SelectionScreen_SetupIcon(state->kinds[entryIndex],
746 state->bases[entryIndex], node, 1);
747 node = node->next;
748 entryIndex++;
749 } while (node != NULL);
750 }
751 state->cursorIndex = 0;
752 state->top = 0;
753 node = state->head;
754 y = node->x + 16;
755 node = node->next;
756 while (node != NULL) {
757 node->targetX = y;
758 node->dx = 12;
759 node = node->next;
760 y += 16;
761 }
762 state->records[1].kind = 1;
763 } else if (state->cursorIndex == 4 && end + 1 < state->count) {
764 state->cursorIndex--;
765 state->records[1].base = 8;
766 state->top++;
767 Menu_ScrollSelectionList(state, 1);
768 if (state->top + state->cursorIndex + 2 == state->count)
769 state->records[1].kind = 0;
770 state->records[0].kind = 1;
771 }
772 } else if (state->cursorIndex == state->count) {
773 state->cursorIndex = 0;
774 }
775 state->status = NODE_STATUS_SHOWN;
777 WaitFrames(1);
779 WaitFrames(1);
780}
781
782/// Moves the cursor one entry left, scrolling the row at its edge and
783/// wrapping from the first entry to the last.
784void Menu_StepLeft(struct SelectionScreen *state) {
785 struct SelectionNode *node;
786 s32 i;
787
790 WaitFrames(1);
791 if (state->count > 5) {
792 if ((state->cursorIndex | state->top) != 0) {
793 if (state->cursorIndex == 1 && state->top != 0) {
794 state->records[0].base = 8;
795 state->top--;
796 Menu_ScrollSelectionList(state, 0);
797 if (state->top == 0)
798 state->records[0].kind = 0;
799 state->records[1].kind = 1;
800 } else {
801 state->cursorIndex--;
802 }
803 } else {
804 node = state->head;
805 i = 64;
806 {
807 /* FAKEMATCH(pin): the zero in r0, live across the first loop as the
808 * native has it; as a plain store of 0, 6 of 184 instructions differ
809 * in tbs-en. */
810 register s32 z asm("r0") = 0;
811 state->records[1].kind = z;
812 }
813 while (node->next != NULL) {
814 node->targetX = node->x + i;
815 node->dx = 12;
816 node = node->next;
817 i -= 16;
818 }
819 node = state->head;
820 while (node->x != node->targetX)
821 WaitFrames(1);
822 // Keep the native count-up: assigning count - 5 directly removes
823 // 20 bytes from the English object.
824 i = 0;
825 while (i != state->count - 5)
826 i++;
827 node = state->head;
828 state->top = i;
829 state->cursorIndex = 4;
830 while (node != NULL) {
831 SelectionScreen_SetupIcon(state->kinds[i], state->bases[i], node, 1);
832 node = node->next;
833 i++;
834 }
835 node = state->head;
836 i = state->baseX;
837 while (node->next != NULL) {
838 node->targetX = i;
839 node->dx = -12;
840 node = node->next;
841 i += 16;
842 }
843 state->records[0].kind = 1;
844 }
845 } else if (state->cursorIndex != 0) {
846 state->cursorIndex--;
847 } else {
848 state->cursorIndex = state->count - 1;
849 }
850 state->status = NODE_STATUS_SHOWN;
852 WaitFrames(1);
854 WaitFrames(1);
855}
856
857/// Redraws the command icon at row place rowIndex in its plain state.
858void SelectionScreen_RedrawIcon(struct SelectionScreen *state, u32 rowIndex) {
859 struct SelectionNode *node = state->head;
860 u32 tile;
861 u32 value;
862
863 while (rowIndex != 0) {
864 rowIndex--;
865 node = node->next;
866 }
867 if (node->kind == 1 || node->kind == 6) {
868 u32 first = node->message - MsgCommandName;
869
870 value = node->slot;
871 Ui_BuildPairedPatternsToSlot(first, 0, &value, &tile, 1);
872 }
873}
874
875/// Redraws the command icon at row place rowIndex and loads its large icon.
877 u32 rowIndex) {
878 struct SelectionNode *node = state->head;
879 u32 tile;
880 u32 value;
881
882 while (rowIndex != 0) {
883 rowIndex--;
884 node = node->next;
885 }
886 if (node->kind == 1 || node->kind == 6) {
887 u32 resource = node->message - MsgCommandName;
888
889 value = node->slot;
890 Ui_BuildPairedPatternsToSlot(resource, 0, &value, &tile, 1);
892 }
893}
894
895/// Tells the battle presentation how many icons the row shows.
897 u16 data[6];
898 struct SelectionNode *node = screen->head;
899 s32 count = 0;
900
901 while (node != 0) {
902 node = node->next;
903 count++;
904 }
905 data[count] = 0xff;
907}
908
909/// Scrolls the row one entry: forward brings an icon in from the right as the
910/// leftmost shrinks away, and back the reverse; waits until it has moved.
911/// Releases the departing cache slot only after its shrinking animation
912/// finishes.
913void Menu_ScrollSelectionList(struct SelectionScreen *screen, s32 forward) {
914 struct SelectionNode *node;
915 struct SelectionNode *last;
916 struct SelectionNode *first;
917 s32 base;
918 s32 kind;
919 u32 entryIndex;
920 s32 rowX;
921 s32 rowY;
922
923 if (forward != 0) {
924 entryIndex = screen->top + SELECTION_ROWS;
925 base = screen->bases[entryIndex];
926 kind = screen->kinds[entryIndex];
928 if (node == NULL)
929 return;
931 rowX = screen->baseX;
932 node->x = rowX + 80;
933 rowY = screen->baseY;
934 node->targetX = rowX + 64;
935 node->y = rowY;
936 node->targetY = rowY;
937 node->scaleStep = 32;
938 node->scale = 32;
939 node->scaleEnd = 256;
940 node->dx = -2;
941 last = node;
942 node = screen->head;
943 node->scaleStep = -32;
944 node->scaleEnd = 0;
945 for (;;) {
946 node->targetX = node->x - 16;
947 node->dx = -2;
948 if (node->next == NULL)
949 break;
950 node = node->next;
951 }
952 node->next = last;
953 last->next = NULL;
954 last->prev = node;
955 node = screen->head;
956 do {
957 WaitFrames(1);
958 } while (node->scale != 0);
959 screen->head = node->next;
961 node->kind = 0;
962 node = node->next;
963 node->prev = NULL;
964 } else {
965 entryIndex = screen->top;
966 base = screen->bases[entryIndex];
967 kind = screen->kinds[entryIndex];
969 if (node == NULL)
970 return;
972 node->x = screen->baseX - 16;
973 node->y = screen->baseY;
974 node->targetY = node->y;
975 node->dx = 2;
976 node->scale = 32;
977 node->scaleStep = 32;
978 node->targetX = node->x + 16;
979 node->scaleEnd = 256;
980 first = node;
981 node = screen->head;
982 node->prev = first;
983 first->next = node;
984 first->prev = NULL;
985 screen->head = first;
986 node = first;
987 for (;;) {
988 node->targetX = node->x + 16;
989 node->dx = 2;
990 if (node->next == NULL)
991 break;
992 node = node->next;
993 }
994 node->scaleEnd = 0;
995 node->scaleStep = -32;
996 node = screen->head;
997 do {
998 WaitFrames(1);
999 } while (node->scale != 256);
1000 while (node->next != NULL)
1001 node = node->next;
1003 node->kind = 0;
1004 node->prev->next = NULL;
1005 }
1006}
1007
1008/// Loads the icon of an entry of kind mode (1 and 6 commands, 2 items, 4
1009/// Psynergy, 9 fixed images) into a free sprite tile slot and returns it, or
1010/// -1.
1012 s32 output;
1013 s32 result = -1;
1014
1015 switch (mode) {
1016 case 1:
1017 case 6:
1018 Ui_BuildPairedPatternsToSlot(value, 0, &result, &output, 0);
1019 break;
1020 case 2:
1021 result = Resource_FindFreeEntry();
1022 if (result == VRAM_CACHE_ENTRY_COUNT)
1023 return -1;
1024 UiIcon_CopyResourceToSlot(value, 0x1a, result);
1025 break;
1026 case 9:
1027 result = Resource_FindFreeEntry();
1028 if (result == VRAM_CACHE_ENTRY_COUNT)
1029 return -1;
1030 RenderResource_LoadTableEntry(value, 0, result);
1031 break;
1032 case 4:
1033 Ability_LoadGlyph(value, 1, &result, &output, 0);
1034 break;
1035 }
1036 return result;
1037}
1038
1039/// Loads the icon of an entry of kind mode into sprite tile slot result (a free
1040/// slot when -1) and returns the slot. Kind 7 is an item icon without its
1041/// count, 8 one of the other icons.
1042s32 Resource_LoadByModeIntoSlot(s32 mode, s32 value, s32 result, s32 option) {
1043 s32 output;
1044 s32 original = result;
1045
1046 if (result == -1) {
1047 result = Resource_FindFreeEntry();
1048 if (result == VRAM_CACHE_ENTRY_COUNT)
1049 return original;
1050 }
1051
1052 switch (mode) {
1053 case 1:
1054 case 6:
1055 Ui_BuildPairedPatternsToSlot(value, option, &result, &output, 1);
1056 break;
1057 case 2:
1058 UiIcon_CopyResourceToSlot(value, 58, result);
1059 break;
1060 case 7:
1061 UiIcon_CopyResourceToSlot(value, 42, result);
1062 break;
1063 case 4:
1064 Ability_LoadGlyph(value, option, &result, &output, 1);
1065 break;
1066 case 8:
1067 Ui_BuildPatternToSlot(value, 0, result);
1068 break;
1069 case 9:
1070 RenderResource_LoadTableEntry(value, 0, result);
1071 break;
1072 }
1073
1074 return result;
1075}
1076
1077/// Sets up a selection icon for an entry: its icon tiles (in its old slot when
1078/// reuse is set), its name message and its sprite.
1079/// kind must select a command, item or Psynergy with the matching base ID.
1081 s32 reuse) {
1082 s32 cacheSlot;
1083 s32 tile;
1084 struct SelectionSprite *sprite;
1085
1086 switch (kind) {
1087 case 1:
1088 case 6:
1089 if (reuse != 0)
1090 cacheSlot = node->slot;
1091 Ui_BuildPairedPatternsToSlot(base, 0, &cacheSlot, &tile, reuse);
1092 node->message = base + MsgCommandName;
1093 break;
1094 case 2:
1095 if (reuse != 0)
1096 cacheSlot = node->slot;
1097 UiIcon_BuildItemIconTiles(base, 1, &cacheSlot, &tile, reuse);
1098 node->message = base + MsgItemName;
1099 break;
1100 case 4:
1101 if (reuse != 0)
1102 cacheSlot = node->slot;
1103 Ability_LoadGlyph(base, 1, &cacheSlot, &tile, reuse);
1104 node->message = base + MsgAbilityName;
1105 break;
1106 }
1107
1108 node->base = base;
1109 node->slot = cacheSlot;
1110 node->tile = tile;
1111 node->kind = kind;
1112 node->scale = 0x100;
1113 node->scaleEnd = 0x100;
1114
1115 sprite = &node->sprite;
1116 sprite->mode = 0;
1117 sprite->colors = 0;
1118 sprite->mosaic = 0;
1119
1120 sprite->size = 1;
1121 sprite->shape = 0;
1122 sprite->palette = 0;
1123 sprite->tile = tile;
1124 sprite->priority = 0;
1125}
1126
1127/// Chooses the entry under the cursor: the other icons gather into it and
1128/// vanish, and it joins the chosen icons at the top left. Returns the entry's
1129/// index.
1130/// The selected row node and a free chosen-icon record must exist before
1131/// confirming.
1133 struct SelectionNode *node;
1134 struct SelectionNode *other = NULL;
1135 u32 nodeIndex = 0;
1136 u32 chosenIndex;
1137 struct SelectionSprite *sprite;
1138
1139 chosenIndex = screen->top + screen->cursorIndex;
1140 Menu_SendNodeCountList(screen);
1141 SelectionScreen_RedrawIcon(screen, screen->cursorIndex);
1142 screen->status = NODE_STATUS_SCROLLING;
1143 WaitFrames(1);
1144 screen->records[0].kind = 0;
1145 screen->records[1].kind = 0;
1146 screen->records[14].kind = 0;
1147 screen->records[14].scale = 0;
1149 node = screen->head;
1150 while (node != NULL && screen->cursorIndex != nodeIndex) {
1151 node = node->next;
1152 nodeIndex++;
1153 }
1154 node->homeX = node->x;
1155 node->homeY = node->y;
1156 for (other = screen->head; other != NULL; other = other->next) {
1157 if (other != node) {
1158 other->targetX = node->x;
1159 other->dx = (node->x - other->x) >> 1;
1160 }
1161 }
1162 WaitFrames(2);
1163 for (other = screen->head; other != NULL; other = other->next) {
1164 if (other != node) {
1165 Resource_ResetEntry(other->slot);
1166 other->kind = 0;
1167 }
1168 }
1169 screen->head = node;
1170 node->prev = NULL;
1171 node->next = NULL;
1172 node->targetX = 4;
1173 for (other = screen->path, nodeIndex = 0; other != NULL;
1174 other = other->next) {
1175 node->targetX += 16;
1176 nodeIndex++;
1177 }
1178 screen->pathTop[nodeIndex] = screen->top;
1179 screen->pathCursor[nodeIndex] = screen->cursorIndex;
1180 node->dx = (node->targetX - node->x) >> 1;
1181 screen->unk39a = 0;
1182 screen->cursorIndex |= 0x80;
1183 WaitFrames(2);
1185 other->kind = node->kind;
1186 other->message = node->message;
1187 other->base = node->base;
1188 other->slot = node->slot;
1189 other->tile = node->tile;
1190 other->x = node->x;
1191 other->y = node->y;
1192 other->targetX = other->x;
1193 other->targetY = other->y;
1194 other->homeX = node->homeX;
1195 other->homeY = node->homeY;
1196 other->dx = 0;
1197 other->dy = 0;
1198 other->scale = 0x100;
1199 other->scaleEnd = 0x100;
1200 sprite = &other->sprite;
1201 sprite->mode = 0;
1202 sprite->colors = 0;
1203 sprite->mosaic = 0;
1204 sprite->size = 1;
1205 sprite->shape = 0;
1206 sprite->palette = 0;
1207 sprite->tile = other->tile;
1208 node->kind = 0;
1209 screen->head = NULL;
1210 if (screen->path != NULL) {
1211 node = screen->path;
1212 while (node->next != NULL)
1213 node = node->next;
1214 node->next = other;
1215 other->prev = node;
1216 other->next = NULL;
1217 } else {
1218 screen->path = other;
1219 other->prev = NULL;
1220 other->next = NULL;
1221 }
1222 return chosenIndex;
1223}
1224
1225/// Six empty functions; nothing calls the first, the fourth or the fifth.
1232
1233/// Sets up a sprite as the right-pointing arrow, in a free tile slot (returned
1234/// in *slot).
1235/// The caller owns the cache slot and releases it through
1236/// UiTextResource_Release.
1237void UiTextResource_Initialize(struct MenuSprite *sprite, s32 *slot) {
1238 const void *data = gMenu_CursorObjectTiles;
1239 s32 cacheSlot = Resource_FindFreeEntry();
1240
1241 *slot = cacheSlot;
1242 sprite->oam.f.tile = VramCache_Load(cacheSlot, 0x80, data);
1243 sprite->oam.f.mode = 0;
1244 sprite->oam.f.mosaic = 0;
1245 sprite->oam.f.colors = 1;
1246 sprite->oam.f.affine = 0;
1247 sprite->oam.f.affineIndex = 0;
1248 sprite->oam.f.size = 0;
1249 sprite->oam.f.shape = 2;
1250 sprite->oam.f.priority = 0;
1251}
1252
1253/// Places an arrow sprite at (x, y) and queues it for drawing.
1255 sprite->oam.f.x = x;
1256 sprite->oam.f.y = y;
1257 Runtime_PushSlotEntry(sprite, 0xFC);
1258}
1259
1260/// Frees an arrow sprite's tile slot.
1262
1263/// Loads the large icon of the command under the cursor, zooming in.
1265 struct SelectionScreen *state = gResQueueWork;
1266 struct SelectionNode *selected = Selection_GetCursorNode(state);
1267 struct SelectionNode *transfer;
1268 GlyphTransfer *buffer;
1269 u8 *table;
1270 void *resource;
1271 s32 resourceId;
1272
1273 if (selected->kind != 1 && selected->kind != 6)
1274 return;
1275
1276 buffer = Runtime_AllocateHeapBlock(17, sizeof(GlyphTransfer));
1277 transfer = &state->records[15];
1278 resourceId = selected->base;
1280 {
1281 u8 **tiles = &buffer->encoded;
1282 resource = table + *(u16 *)(table + selected->base * 2);
1283 *tiles = resource;
1284 }
1285 Resource_DecodeByteLz(resource, buffer);
1286
1287 if (transfer->kind == 0)
1288 transfer->slot = Resource_FindFreeEntry();
1289 transfer->tile = VramCache_Load(transfer->slot, 0x400, buffer);
1290 transfer->kind = 1;
1291 transfer->base = resourceId;
1292 transfer->scale = 40;
1293 transfer->scaleStep = 40;
1294 transfer->scaleEnd = 240;
1296}
1297
1298/// Frees the large command icon, if it is shown.
1299/// The large preview owns a cache slot independently of the visible row icons.
1301 struct SelectionNode *largeIcon = &gResQueueWork->records[15];
1302
1303 if (largeIcon->kind != 0) {
1304 Resource_ResetEntry(largeIcon->slot);
1305 largeIcon->kind = 0;
1306 }
1307}
1308
1309#if TBS_PATCH_2
1310
1311#define HAS_LOCALIZED_MENU_GUARD 1
1312#endif
1313
1314/// Runs the field menu until the player picks something that leaves it, and
1315/// returns that choice's result.
1317 s32 ret;
1318 s32 selection;
1319 u8 *state;
1320
1321 state = (u8 *)gEventWork;
1322 selection = 0;
1323
1324 for (;;) {
1326 selection = Menu_SelectTopEntry(selection);
1327#if defined(HAS_LOCALIZED_MENU_GUARD)
1328 state[0xcca] = 1;
1329 if (*(s16 *)(state + 0xcb8) != 0) {
1330 BattleFx_ClearRandomParticlesFar();
1331 WaitFrames(1);
1332 }
1333#endif
1334#ifdef UBFIX
1335 // UB: the original reads a void return. The default result is ignored by
1336 // the only caller, so give it a defined value after closing the window.
1338 ret = 0;
1339#else
1340 ret = UiWork_CloseAndRelease();
1341#endif
1342
1343 switch (selection) {
1344 case 0:
1346 if (ret == 0)
1347 ret = 0xff;
1348 ((struct EventWork *)state)->facingTrigger = ret;
1349 break;
1350 case 1:
1351 ret = PsynergyMenu_RunFar();
1352 if (ret == -1)
1353 continue;
1354 break;
1355 case 2:
1356 ret = DjinnMenu_RunFar();
1357 if (ret != 0)
1358 continue;
1359 break;
1360 case 3:
1361 ret = ItemMenu_RunFar();
1362 if (ret == -1)
1363 continue;
1364 break;
1365 case 4:
1366 ret = StatusMenu_RunFar();
1367 if (ret == -1)
1368 continue;
1369 break;
1370 default:
1371 break;
1372 }
1373 break;
1374 }
1375
1376#if defined(HAS_LOCALIZED_MENU_GUARD)
1377 state[0xcca] = 0;
1378#endif
1379 return ret;
1380}
1381
1382/// Opens the field menu's window and waits a frame.
1385 WaitFrames(1);
1386}
1387
1388/// Closes the window kept in heap block 16 and frees the block.
1390
1391/// Sets up an empty selection screen and waits a frame.
1392/// Nothing calls it.
1396 WaitFrames(1);
1397}
1398
1399/// Runs a selection row with the cursor on entry initialIndex, cancellable,
1400/// and returns the entry chosen or -1.
1401/// initialIndex is a row index; cancellation returns -1 encoded as u32.
1403 struct SelectionScreen *screen = gResQueueWork;
1404 u32 result;
1405
1406 screen->cursorIndex = initialIndex;
1407 screen->locked = 1;
1408 MenuSelection_BuildEntries(initialIndex);
1412 result = Menu_WaitForSelectionInput(1);
1414 return result;
1415}
static s32 * EffectPosition_Coordinates(struct EffectPosition *position)
Returns the position's three coordinates as an array.
Definition effect_step.h:68
void BattlePres_SetActorModesFar(u16 *actors, s32 mode)
s32 BattleMotion_ProjectScaledPositionFar(s32 id, s32 *projected)
s32 GameFlag_TestFar(s32 flag)
s32 StatusMenu_RunFar(void)
s32 DjinnMenu_RunFar(void)
s32 ItemMenu_RunFar(void)
s32 PsynergyMenu_RunFar(void)
s32 Object_GetTriggerTileAheadOfCurrentFar(void)
void AudioCommand_PlayFar(s32 id)
#define FLAG_IN_BATTLE
Set as a battle starts, cleared as a field scene starts.
Definition flags.h:21
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
u32 gFrameTick
Counted up by every VBlank.
const u8 gMenu_CursorObjectTiles[]
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
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
Definition heap.c:47
s32 Menu_SelectTopEntry(s32 selection)
Builds the field command menu, omitting Djinn when none are owned.
Definition icon_menu.c:448
@ KEY_B
Definition io_reg.h:244
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_RIGHT
Definition io_reg.h:247
@ KEY_A
Definition io_reg.h:243
volatile u32 gKeysPressed
Keys that went down this frame.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
void Runtime_ReleaseHeapBlock(s32 slot)
u8 gMenu_CursorLeftObjectTiles[]
struct SelectionScreen * gResQueueWork
const u8 gMenu_AnimatedCursorTiles[]
void UiWindow_CreateWithLayoutBounds(s32 flags)
Opens the party status window with flags (see PARTY_STATUS_*) in a new heap block and draws it.
void PartyStatus_Close(void)
Closes the party status window and frees its heap block.
s32 AffineMatrix_BuildForEffect(struct AffineTransform *source)
Hands out the next OAM affine matrix for a sprite drawn with source's scale and rotation and fills it...
Definition render.c:27
void Runtime_PushSlotEntry(void *slotEntry, s32 slot)
Links a sprite entry into depth slot slot (clamped to 0..255) for this frame.
Definition render.c:79
char ResourceId_CommandIcons
s32 Resource_DecodeByteLz(const void *source, void *destination)
Decodes a byte-oriented LZ resource and returns its unpacked byte count.
Definition decompress.c:37
const s8 gMenu_CursorBobOffsets[16]
The selection cursor's bob: a 16-step wave of up to 3 pixels each way.
Definition scales.c:23
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
UNUSED void Menu_MoveSelectionBackward(struct SelectionScreen *screen)
Moves the cursor one entry left, scrolling the row at its second place.
Definition selection.c:685
void Menu_SetupSelectionBothSides(void)
Sets up both end arrows of the selection row.
Definition selection.c:508
void Menu_OpenSelectionWindow(s32 mode, u32 count)
Opens or refits the name window above the selection row and writes the name of the icon under the cur...
Definition selection.c:410
void UiGlyph_ResetWorkState(void)
Allocates and resets the selection screen: the row of icons the player picks from,...
Definition selection.c:22
static __inline__ void ResetCursor(struct GlyphCursor *cursor)
Definition selection.c:13
void Resource_ScheduleOwnerReset(void)
Stops drawing the selection screen.
Definition selection.c:185
void Resource_ClearOwnerListAndCounters(void)
Empties the selection screen's list of entries.
Definition selection.c:70
s32 Resource_LoadByMode(s32 mode, s32 value)
Loads the icon of an entry of kind mode (1 and 6 commands, 2 items, 4 Psynergy, 9 fixed images) into ...
Definition selection.c:1011
void SelectionScreen_LoadLargeIcon(void)
Loads the large icon of the command under the cursor, zooming in.
Definition selection.c:1264
void Resource_PushPendingPair(u32 kind, u32 base)
Adds an entry (kind and id) to the selection screen's list, up to 16.
Definition selection.c:86
UNUSED void Menu_MoveSelectionForward(struct SelectionScreen *screen)
Moves the cursor one entry right, scrolling the row at its fourth place.
Definition selection.c:655
UNUSED void UiTextResource_NoOpCallback2(void)
Definition selection.c:1229
s32 Resource_LoadByModeIntoSlot(s32 mode, s32 value, s32 result, s32 option)
Loads the icon of an entry of kind mode into sprite tile slot result (a free slot when -1) and return...
Definition selection.c:1042
void Menu_SetNodeCoordinates(u32 x, u32 y)
Moves the row of icons to start at pixel (x, y), 16 pixels apart.
Definition selection.c:490
void Menu_StepRight(struct SelectionScreen *state)
Moves the cursor one entry right, scrolling the row at its edge and wrapping from the last entry to t...
Definition selection.c:715
#define NODE_STATUS_SCROLLING
Definition selection.c:576
u32 Menu_RunSelectionForValue(u32 initialIndex)
Runs a selection row with the cursor on entry initialIndex, cancellable, and returns the entry chosen...
Definition selection.c:1402
#define SELECTION_FIXED
Definition selection.c:574
void Resource_ResetPendingTransfer(void)
Frees the large command icon, if it is shown.
Definition selection.c:1300
void UiTextResource_Initialize(struct MenuSprite *sprite, s32 *slot)
Sets up a sprite as the right-pointing arrow, in a free tile slot (returned in *slot).
Definition selection.c:1237
void SelectionScreen_DrawArrow(struct SelectionScreen *state, s32 side)
Draws the selection screen's left (index 0) or right (1) arrow, nudged outwards while it flashes afte...
Definition selection.c:373
u32 Menu_ConfirmSelection(struct SelectionScreen *screen)
Chooses the entry under the cursor: the other icons gather into it and vanish, and it joins the chose...
Definition selection.c:1132
void SelectionScreen_RedrawIcon(struct SelectionScreen *state, u32 rowIndex)
Redraws the command icon at row place rowIndex in its plain state.
Definition selection.c:858
#define ARROW_SCROLL_FRAMES
Definition selection.c:582
void UiTextResource_Release(s32 value)
Frees an arrow sprite's tile slot.
Definition selection.c:1261
void UiTextResource_SetPosition(struct MenuSprite *sprite, s32 x, s32 y)
Places an arrow sprite at (x, y) and queues it for drawing.
Definition selection.c:1254
void MenuSelection_BuildEntries(u32 unused)
Creates icons for the first five listed entries in a row along the bottom of the screen.
Definition selection.c:101
struct SelectionNode * SelectionScreen_FindFreeIcon(s32 kind)
Returns a free selection icon record: one of the seven row icons (kind 0) or of the five chosen icons...
Definition selection.c:161
void UiTextResource_NoOpCallback4(void)
Definition selection.c:1231
struct SelectionNode * Selection_GetCursorNode(struct SelectionScreen *screen)
Returns the node at the selection screen's cursor index.
Definition selection.c:564
void Menu_ScrollSelectionList(struct SelectionScreen *screen, s32 forward)
Scrolls the row one entry: forward brings an icon in from the right as the leftmost shrinks away,...
Definition selection.c:913
void SelectionScreen_SetupArrow(struct SelectionScreen *state, s32 side)
Sets up the left (index 0) or right (1) arrow of the selection row, shown when there are entries beyo...
Definition selection.c:518
#define NODE_KIND_YES_NO
Definition selection.c:579
void SelectionScreen_SetupIcon(u32 kind, s32 base, struct SelectionNode *node, s32 reuse)
Sets up a selection icon for an entry: its icon tiles (in its old slot when reuse is set),...
Definition selection.c:1080
void UiWork_CloseAndRelease(void)
Closes the window kept in heap block 16 and frees the block.
Definition selection.c:1389
UNUSED void SelectionScreen_CreateEmpty(void)
Sets up an empty selection screen and waits a frame.
Definition selection.c:1393
void Resource_ScheduleOwnerResetDelayed(void)
Starts drawing the selection screen each frame.
Definition selection.c:180
#define SELECTION_ROWS
Definition selection.c:581
UNUSED void UiTextResource_NoOpCallback3(void)
Definition selection.c:1230
s32 Menu_SelectionLoop(s32 mode)
Runs the selection row until the player chooses (the chosen entry's index) or, when mode allows it,...
Definition selection.c:587
void UiTextResource_NoOpCallbackBank(void)
Definition selection.c:1227
void Resource_ResetOwnerEntries(void)
Closes the selection screen and frees its icons, tiles and work block.
Definition selection.c:455
void UiWindow_OpenMode1AndWaitFrame(void)
Opens the field menu's window and waits a frame.
Definition selection.c:1383
#define NODE_STATUS_SHOWN
Definition selection.c:577
void SelectionScreen_Draw(void)
The selection screen's per-frame callback: slides and draws the row of icons, the large icon over the...
Definition selection.c:192
u32 Menu_WaitForSelectionInput(u32 mode)
As Menu_SelectionLoop, with the menu sounds.
Definition selection.c:612
void UiWork_ReservedNoOp(void)
Definition selection.c:157
s32 Menu_RunTopSelection(void)
Runs the field menu until the player picks something that leaves it, and returns that choice's result...
Definition selection.c:1316
void Menu_SendNodeCountList(struct SelectionScreen *screen)
Tells the battle presentation how many icons the row shows.
Definition selection.c:896
void UiTextResource_NoOpCallback1(void)
Definition selection.c:1228
UNUSED void UiTextResource_NoOpCallback(void)
Six empty functions; nothing calls the first, the fourth or the fifth.
Definition selection.c:1226
void SelectionScreen_HighlightIcon(struct SelectionScreen *state, u32 rowIndex)
Redraws the command icon at row place rowIndex and loads its large icon.
Definition selection.c:876
void Menu_StepLeft(struct SelectionScreen *state)
Moves the cursor one entry left, scrolling the row at its edge and wrapping from the first entry to t...
Definition selection.c:784
#define SE_MENU_CANCEL
Definition songs.h:106
#define SE_MENU_CURSOR_MOVE
Definition songs.h:104
#define SE_MENU_CONFIRM
Definition songs.h:105
struct EventWork * gEventWork
#define NULL
Definition bilibin.h:6
u16 angle
1/65536 turns
Definition affine.h:16
u16 scaleY
8.8 fixed point, read signed
Definition affine.h:15
u16 scaleX
8.8 fixed point, read signed: negative mirrors the sprite
Definition affine.h:14
A point projected onto the screen, with its depth.
Definition effect_step.h:46
s32 y
screen pixels
Definition effect_step.h:59
s32 x
screen pixels
Definition effect_step.h:58
The running scene's event work: its placement and event tables, its actors, the triggers and exit it ...
Definition event_work.h:20
s16 facingTrigger
the collision code ahead, which a search answers
Definition event_work.h:31
Two halfwords of a selection record, the second cleared as its cursor.
Definition selection.c:8
u8 * encoded
Definition glyph.h:43
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
An icon of the selection screen: its list links, the entry it shows, its place and its slide toward a...
Definition select.h:31
s16 dy
pixels a frame
Definition select.h:41
s16 dx
pixels a frame
Definition select.h:40
u16 tile
first sprite tile of its picture
Definition select.h:37
s16 scaleEnd
8.8 fixed point, 0x100 full size
Definition select.h:49
s16 scale
8.8 fixed point, 0x100 full size
Definition select.h:47
struct SelectionNode * next
the icon after it in its row
Definition select.h:33
s16 scaleStep
8.8 fixed point a frame
Definition select.h:48
s16 targetX
screen pixels
Definition select.h:42
u16 message
its name, shown in the screen's window
Definition select.h:46
struct SelectionNode * prev
the icon before it in its row
Definition select.h:32
s16 homeX
screen pixels, where it stood when chosen
Definition select.h:44
u16 kind
the entry's kind, as listed in SelectionScreen.kinds; 0 free
Definition select.h:35
u16 base
the entry's id, as listed in SelectionScreen.bases
Definition select.h:34
struct SelectionSprite sprite
Definition select.h:50
s16 targetY
screen pixels
Definition select.h:43
s16 homeY
screen pixels, where it stood when chosen
Definition select.h:45
s16 x
screen pixels
Definition select.h:38
u16 slot
VRAM cache slot of its picture.
Definition select.h:36
s16 y
screen pixels
Definition select.h:39
The selection screen (heap block 18): the row of icons the player picks from, with arrows at each end...
Definition select.h:55
u16 pathTop[5]
top, kept for each icon chosen on the path
Definition select.h:77
struct UiWindow * window
the window naming the chosen entry
Definition select.h:61
u16 verticalScroll
pixels added to the icons' y; 32 at setup
Definition select.h:75
struct AffineTransform transform
a zooming icon's scale
Definition select.h:58
u16 status
1 shown, 33 while scrolling; counts up each frame drawn
Definition select.h:76
u16 top
the first listed entry shown
Definition select.h:71
u16 pathCursor[5]
cursorIndex, kept for each icon chosen on the path
Definition select.h:78
u16 locked
999 from setup on.
Definition select.h:81
struct SelectionNode * path
the icons chosen so far
Definition select.h:60
u16 baseY
screen pixels
Definition select.h:69
u16 bases[16]
Definition select.h:65
u16 cursorIndex
The entry under the hand, from top; bit 7 asks the next list to start again from its first entry.
Definition select.h:74
u16 kinds[16]
The listed entries, up to 16 (Resource_PushPendingPair).
Definition select.h:64
struct SelectionNode records[16]
The icons; 14 is the pointing hand, whose picture is loaded at setup.
Definition select.h:57
struct SelectionNode * head
the first icon of the row
Definition select.h:59
u16 unk39a
cleared with the list; not read by name in TBS
Definition select.h:70
u16 baseX
screen pixels
Definition select.h:68
A selection screen sprite: a list link and its OAM attributes.
Definition select.h:13
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
u16 width
tiles
Definition uiwindow.h:13
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
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 short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
#define TRUE
Definition types.h:21
#define FALSE
Definition types.h:20
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
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 Resource_FindFreeEntry(void)
Returns the number of the first free cache entry, or VRAM_CACHE_ENTRY_COUNT when all are taken.
Definition vram_cache.c:211
s32 VramCache_Load(u32 no, u32 size, const void *src)
Gives cache entry no size bytes of sprite VRAM and copies src there.
Definition vram_cache.c:143
@ VRAM_CACHE_ENTRY_COUNT
Definition vram_tab.h:12
s32 Ui_BuildPatternToSlot(s32 icon, s32 unused, s32 cacheSlot)
Builds one of the other icons and loads it into sprite tile slot cacheSlot.
Definition icons.c:177
s32 UiIcon_CopyResourceToSlot(s32 inventoryCode, s32 layers, s32 cacheSlot)
Composes an inventory icon with the requested layers and loads it into cacheSlot.
Definition icons.c:166
s32 RenderResource_LoadTableEntry(u32 value, s32 unused, u32 slot)
Loads one of four small fixed images into the sprite tile slot named by slot.
Definition icons.c:190
void Ui_BuildPairedPatternsToSlot(s32 overlayIcon, s32 frameIcon, s32 *slot, s32 *tileOut, s32 reuse)
Builds a command icon (overlay overlayIcon over frame frameIcon) and loads it into a sprite tile slot...
Definition icons.c:20
void Ability_LoadGlyph(s32 action, s32 withBase, s32 *slot, s32 *tile, s32 reuse)
Builds the Psynergy icon of a battle action, as UiIcon_BuildAbilityIconTiles.
Definition icons.c:234
void UiIcon_BuildItemIconTiles(u32 glyph, s32 withBase, s32 *cacheSlot, s32 *tileOut, s32 reuse)
Builds the item icon glyph, over the icon frame when withBase is set, and loads it into *cacheSlot (a...
Definition icons.c:52
What every part of the window object shares: its includes, edition values, macros and the codes of de...
#define UI_SELECTION_ENTRY_LIMIT
void RenderOutput_PrepareForRedraw(struct UiWindow *window)
Clears a window's contents: redraws its empty frame and releases the render outputs it carries.
Definition windows.c:392
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