Alchemy
Loading...
Searching...
No Matches

common.c

Go to the documentation of this file.
1/// @file
2/// The pieces the menu screens share: windows, the status panel, numbers,
3/// icons, the party figures, the hand cursor, paged lists, palettes and the
4/// Start watch.
5/// Part of menu.c, the menu object, compiled only through it.
6
7#include "../menu_internal.h"
8
9// The status panel's name and ailment column starts further left in the
10// international editions, whose ailment labels are longer, and so does
11// "Cannot equip".
12#if TBS_PATCH_1
13#define STATUS_PANEL_TEXT_X 32
14#define STATUS_PANEL_CANNOT_EQUIP_X 0
15#else
16#define STATUS_PANEL_TEXT_X 40
17#define STATUS_PANEL_CANNOT_EQUIP_X 16
18#endif
19
20// A Psynergy item's panel: Spanish puts "Learned" or "Will learn" above the
21// Psynergy's name, the other editions below it.
22#if LANGUAGE == LANGUAGE_SPANISH
23#define STATUS_PANEL_LEARN_NAME_Y 56
24#define STATUS_PANEL_LEARN_STATUS_Y 48
25#else
26#define STATUS_PANEL_LEARN_NAME_Y 48
27#define STATUS_PANEL_LEARN_STATUS_Y 56
28#endif
29
30/// UiWindow_UpdateOrCreate: keep an existing window as it is, without redrawing
31/// its saved rectangle. The low byte of the flags is the window style.
32#define WINDOW_KEEP_EXISTING 0x100
33#define WINDOW_STYLE_MASK 0xff
34
35/// Resumes the overlay tasks and tile animations when a menu closes, and
36/// clears game flags 0x166 and 0x152.
37/// Returns nothing useful; callers ignore the value.
41 // Flag 0x166: its meaning is not known yet.
43 // Flag 0x152, while set, stops BattlePalette_UpdateBlend.
45#ifdef UBFIX
46 return 0;
47#endif
48}
49
50/// Suspends the overlay tasks and tile animations while a menu is open, and
51/// sets flags 0x152 and 0x166. Returns the scheduler's result.
53 GameFlag_SetBitFar(0x152);
54 GameFlag_SetBitFar(0x166);
57}
58
59/// Clears the whole menu work and sets its defaults: no pane selected, one
60/// entry in each pane, and a 1x1 cursor grid.
62 struct InventoryMenuState *work = gMenuWork;
63
64 Dma_Fill32(0, work, MENU_WORK_SIZE);
65 work->paneIndex[0] = -1;
66 work->paneCount[0] = 1;
67 work->paneCount[1] = 1;
68 work->columnCount = 1;
69 work->rowCount = 1;
70}
71
72/// Opens the window kept in *handle, or redraws it if it is already open.
73///
74/// If *handle is empty, creates a window at (x, y), w by h tiles, in the style
75/// given by the low byte of flags, stores it in *handle and returns 1. If the
76/// window exists, redraws its saved rectangle (unless flags has
77/// WINDOW_KEEP_EXISTING) and returns 0.
78s32 UiWindow_UpdateOrCreate(struct UiWindow **handle, s32 x, s32 y, s32 w,
79 s32 h, s32 flags) {
80 struct UiWindow *window;
81 s32 style;
82
83 window = *handle;
84 if (window != 0) {
86 return 0;
87 }
89 return 0;
90 }
91 style = flags & WINDOW_STYLE_MASK;
92 *handle = UiWindow_CreateFar(x, y, w, h, style);
93 return 1;
94}
95
96/// Closes the window kept in *handle, if any, and clears the handle. style is
97/// passed on to UiWork_FinalizeFar and chooses how the window closes.
98void UiWindow_CloseIfOpen(struct UiWindow **handle, s32 style) {
99 if (*handle != NULL) {
100 UiWork_FinalizeFar(*handle, style);
101 *handle = NULL;
102 }
103}
104
105/// Copies one BattleUnit with the resident IWRAM word copy.
106static inline void Owner_Copy(struct BattleUnit *destination,
107 struct BattleUnit *source) {
108 _call_via_r3(destination, source, sizeof(struct BattleUnit), IwramCopyWords);
109}
110
111/// Draws the item menu's status panel for the party member owner (window at
112/// tile 0,5, 13 by 12): the name, up to two ailments or the level, and below
113/// them what mode's panel kind asks for. slot is the inventory slot of the
114/// item the panel is about, for the equipment and Psynergy item panels. The
115/// first parameter, the status window, is not used: the window is the menu
116/// work's.
117void Menu_DrawOwnerStatusPanel(struct UiWindow *unused, s32 owner, s32 slot,
118 s32 mode) {
119 s32 created;
120 struct ItemDefinition *def;
121 u32 item;
122 struct InventoryMenuState *state;
123 struct BattleUnit *unit;
124 struct UiWindow *window;
125 s32 ailmentRows;
126 s32 value;
127 u8 ailments[8];
128
129 created = 0;
131 unit = UnitGetFar(owner);
132 item = unit->inventory[slot];
133 def = Item_GetDirectFar(item & ITEM_ID_MASK);
134 if (!(mode & STATUS_PANEL_LOWER_ONLY))
135 created = UiWindow_UpdateOrCreate(&state->statusWindow, 0, 5, 13, 12,
137 window = state->statusWindow;
138
139 // The name, then each ailment the member has, one row each; the level
140 // takes the third row when no more than one ailment is shown.
141 if (!(mode & STATUS_PANEL_LOWER_ONLY)) {
142 if (!created) {
143 WaitFrames(1);
144 UiWindow_ClearInteriorTilesFar(state->statusWindow, 0, 0, 88, 32);
145 }
147 CharacterMenu_BuildAvailability(ailments, 1, owner);
148 ailmentRows = 0;
149 if (ailments[CHARACTER_POISON]) {
150 UiText_DrawCharacterAtOffsetFar(MsgPoisonLabel, window,
151 STATUS_PANEL_TEXT_X, ailmentRows * 8 + 8);
152 ailmentRows++;
153 }
154 if (ailments[CHARACTER_VENOM]) {
155 UiText_DrawCharacterAtOffsetFar(MsgVenomLabel, window,
156 STATUS_PANEL_TEXT_X, ailmentRows * 8 + 8);
157 ailmentRows++;
158 }
159 if (ailments[CHARACTER_CURSE]) {
160 UiText_DrawCharacterAtOffsetFar(MsgCurseLabel, window,
161 STATUS_PANEL_TEXT_X, ailmentRows * 8 + 8);
162 ailmentRows++;
163 }
164 if (ailments[CHARACTER_HAUNT]) {
165 UiText_DrawCharacterAtOffsetFar(MsgHauntLabel, window,
166 STATUS_PANEL_TEXT_X, ailmentRows * 8 + 8);
167 ailmentRows++;
168 }
169 if (ailmentRows < 2) {
170 value = unit->level;
171 MENU_DRAW_STATUS_LABEL(gUi_LvString, window, 40, 16);
172 UiText_DrawNumberInWindowFar(value, 4, window, 56, 16);
173 }
174 }
175
176 // Clear the lower part and redraw the member's portrait.
177 if (!created) {
178 WaitFrames(1);
179 UiWindow_ClearInteriorTilesFar(state->statusWindow, 0, 32, 88, 80);
180 }
182 if (!(mode & STATUS_PANEL_LOWER_ONLY))
183 state->cursor = SideObject_CreateFar(owner, 0, 0, window, 0, 0);
184
185 switch (mode & STATUS_PANEL_KIND_MASK) {
187 value = unit->classIndex + MsgClassName;
188 UiText_DrawCharacterAtOffsetFar(value, window, 0, 32);
189 Ui_DrawValuePairRows(unit, window);
190 value = unit->experience;
191 UiText_DrawCharacterAtOffsetFar(MsgExpLabel, window, 0, 64);
192 UiText_DrawNumberInWindowFar(value, 8, window, 24, 72);
193 break;
195 value = unit->classIndex + MsgClassName;
196 UiText_DrawCharacterAtOffsetFar(value, window, 0, 32);
197 Ui_DrawValuePairRows(unit, window);
198 break;
200 case STATUS_PANEL_EQUIP + 1: { // draws the same panel
201 struct BattleUnit *backup;
202
203 if (!Item_CanOwnerEquip(owner, item)) {
204 UiText_DrawCharacterAtOffsetFar(MsgCannotEquip, window,
206 break;
207 }
208 // Equip (or, previewing a removal, unequip) the item on the real unit,
209 // recalculate its stats, show them against the saved copy, then put the
210 // unit back as it was.
211 backup = MemAlloc(sizeof(struct BattleUnit));
212 Owner_Copy(backup, unit);
213 if (state->equipPreview)
214 unit->inventory[slot] &= ~INVENTORY_EQUIPPED;
215 else
216 Inventory_EquipFar(owner, slot);
217 UnitCalcFar(owner);
218 UiText_DrawStatComparison(unit, backup, window);
219 Owner_Copy(unit, backup);
220 MemFree(backup);
221 break;
222 }
223 case STATUS_PANEL_LEARN: {
224 s32 psynergy = def->actionId;
225 s32 known = 0;
226 s32 i;
227
228 for (i = 0; i < 32; i++) {
230 psynergy) {
231 known = 1;
232 break;
233 }
234 }
235 // The Psynergy's name and "Learned" or "Will learn"; Spanish puts the
236 // label above the name.
237 if (known) {
238 UiText_DrawCharacterAtOffsetFar(psynergy + MsgAbilityName, window, 0,
240 UiText_DrawCharacterAtOffsetFar(MsgLearned, window, 0,
242 } else {
243 UiText_DrawCharacterAtOffsetFar(psynergy + MsgAbilityName, window, 0,
245 UiText_DrawCharacterAtOffsetFar(MsgWillLearn, window, 0,
247 }
248 break;
249 }
250 case STATUS_PANEL_STATS: {
251 // The labels are consecutive messages: Attack, Defense, Status, Luck and
252 // Agility.
253 s32 labels = MsgPanelStatLabel;
254
255 UiText_DrawCharacterAtOffsetFar(labels, window, 0, 40); // "Attack"
256 value = unit->atk;
257 UiText_DrawNumberInWindowFar(value, 3, window, 64, 40);
258 UiText_DrawCharacterAtOffsetFar(labels + 1, window, 0, 48); // "Defense"
259 value = unit->def;
260 UiText_DrawNumberInWindowFar(value, 3, window, 64, 48);
261 UiText_DrawCharacterAtOffsetFar(labels + 4, window, 0, 56); // "Agility"
262 value = unit->agi;
263 UiText_DrawNumberInWindowFar(value, 3, window, 64, 56);
264 UiText_DrawCharacterAtOffsetFar(labels + 3, window, 0, 64); // "Luck"
265 value = unit->luck;
266 UiText_DrawNumberInWindowFar(value, 3, window, 64, 64);
267 break;
268 }
269 }
270}
271
272#if LANGUAGE != LANGUAGE_JAPANESE
273/// The pixels the field allows each digit. The Latin font's digits are 7
274/// pixels wide, so the digits themselves take a pixel less each.
275#define NUMBER_PIXELS_PER_DIGIT 8
276
277/// Returns how many decimal digits number has, but at least 2: 0-99 give 2,
278/// 100-999 give 3, 1000-9999 give 4. The count starts with the units digit,
279/// adds one for each division by ten that leaves 10 or more, then adds the
280/// leading digit; a number under 10 has its one digit counted as both, which
281/// is where the minimum of 2 comes from.
282static inline s32 CountDigitsAtLeastTwo(s32 number) {
283 s32 count;
284
285 // 16 only bounds the loop: an s32 has at most 10 digits, so the count
286 // always stops first.
287 for (count = 1; count < 16; count++) {
288 number /= 10;
289 if (number < 10) {
290 break;
291 }
292 }
293 // The leading digit.
294 count++;
295 return count;
296}
297
298/// Draws number right-aligned in a field that ends at pixel column x and
299/// allows 8 pixels for each digit, at least two digits wide.
300///
301/// The international editions draw a character's HP and PP with it
302/// (Ui_DrawValuePairRows). The Japanese editions draw those figures in
303/// four-character fields padded with spaces, which keeps the digits in line
304/// because the Japanese font's space is as wide as a digit (7 pixels). The
305/// Latin font's space is 5 pixels, so here each figure gets a field as wide
306/// as its digits instead.
307///
308/// The number writer draws the digits 7 pixels apart, so a number ends about
309/// a pixel per digit before x: 99 ends 2 pixels before it, 100 ends 3. A
310/// number under 10 draws as a 5-pixel space and its digit, and ends 4 pixels
311/// before x.
312///
313/// number: the value to draw, 0 or more
314/// x: the field's right edge, in pixels within the window
315/// y: the pixel row of the text, within the window
316void UiText_DrawNumberRightAligned(s32 number, struct UiWindow *window, s32 x,
317 s32 y) {
318 s32 width = CountDigitsAtLeastTwo(number);
319
320 // Step x back to the field's left edge; the number writer right-aligns the
321 // number in a field of width characters. x changes in place: a separate
322 // left-edge local changes the registers.
323 x -= width * NUMBER_PIXELS_PER_DIGIT;
324 UiText_DrawNumberAtOffsetFar(number, width, window, x, y);
325}
326
327#endif
328
329/// Draws a character's HP and PP into window as two rows, "HP current/maximum"
330/// at pixel row 40 and "PP current/maximum" at row 48. Current HP is drawn in
331/// colour 4 when it is below a quarter of maximum HP and in colour 2 at 0;
332/// then the colour goes back to 15, the default text colour.
333void Ui_DrawValuePairRows(struct BattleUnit *unit, struct UiWindow *window) {
334 // Each figure in turn, as an s16. Read straight from unit, the figures
335 // compile differently.
336 s16 value;
337
338#if LANGUAGE != LANGUAGE_JAPANESE
339 // The label at the left and a slash at 48. A current figure ends before
340 // the slash, at 48, and a maximum at 88, each in a field as wide as its
341 // digits.
344 value = unit->maxHp;
345 UiText_DrawNumberRightAligned(value, window, 88, 40);
346 value = unit->hp;
347 if (value < unit->maxHp >> 2) { // below a quarter of maximum HP
349 }
350 if (value == 0) {
352 }
353 UiText_DrawNumberRightAligned(value, window, 48, 40);
357 value = unit->pp;
358 UiText_DrawNumberRightAligned(value, window, 48, 48);
359 value = unit->maxPp;
360 UiText_DrawNumberRightAligned(value, window, 88, 48);
361#else
362 // Each row string ("HP /" and "EP /") holds the label and the slash,
363 // one character to an 8-pixel cell, the slash in the cell at 48. Each
364 // figure is four characters padded with spaces: the current one drawn
365 // from 16 at the font's widths, the maximum from 56 a cell a character,
366 // ending at 88.
368 value = unit->maxHp;
369 UiText_DrawNumberInWindowFar(value, 4, window, 56, 40);
370 value = unit->hp;
371 if (value < unit->maxHp >> 2) { // below a quarter of maximum HP
373 }
374 if (value == 0) {
376 }
377 UiText_DrawNumberAtOffsetFar(value, 4, window, 16, 40);
380 value = unit->pp;
381 UiText_DrawNumberAtOffsetFar(value, 4, window, 16, 48);
382 value = unit->maxPp;
383 UiText_DrawNumberInWindowFar(value, 4, window, 56, 48);
384#endif
385}
386
387/// The stat arrows: the up and down arrow sprites the menu loads into its two
388/// resource slots (Resource_LoadPairedBlocks).
390
391/// Writes Attack, Defense and Agility into a status window as they are now
392/// (before), and beside each one that changes its new value (after) with an up
393/// or down arrow: the equipment preview.
394void UiText_DrawStatComparison(const struct BattleUnit *after,
395 const struct BattleUnit *before,
396 struct UiWindow *window) {
397 UiText_DrawCharacterAtOffsetFar(MsgPanelStatLabel, window, 0, 32);
398 UiText_DrawNumberAtOffsetFar(before->atk, 3, window, 16, 40);
399 if (after->atk != before->atk) {
400 UiText_DrawNumberAtOffsetFar(after->atk, 3, window, 64, 40);
401 if (after->atk > before->atk) {
403 } else {
405 }
406 }
407 UiText_DrawCharacterAtOffsetFar(MsgPanelDefenseLabel, window, 0, 48);
408 UiText_DrawNumberAtOffsetFar(before->def, 3, window, 16, 56);
409 if (after->def != before->def) {
410 UiText_DrawNumberAtOffsetFar(after->def, 3, window, 64, 56);
411 if (after->def > before->def) {
413 } else {
415 }
416 }
417 UiText_DrawCharacterAtOffsetFar(MsgAgilityLabel, window, 0, 64);
418 UiText_DrawNumberAtOffsetFar(before->agi, 3, window, 16, 72);
419 if (after->agi != before->agi) {
420 UiText_DrawNumberAtOffsetFar(after->agi, 3, window, 64, 72);
421 if (after->agi > before->agi) {
423 } else {
425 }
426 }
427}
428
429/// Size of one 16x16 4bpp sprite tile block.
430#define ICON_TILE_BYTES 0x80
431
432/// Creates a hand cursor sprite in window at (x, y), loading the hand's tiles
433/// into a free VRAM block. Returns the sprite, or 0 when no block is free.
434/// Nothing calls it; UiIcon_CreateWithResourceVariant is the one in use.
436 s32 y) {
437 s32 block;
438 s32 icon;
439 icon = 0;
440 block = Resource_FindFreeEntry();
441 if (block != 0) {
443 icon = (s32)RenderOutput_CreateFar(block, ICON_SPRITE_16X16, window, x, y);
444 }
445 return icon;
446}
447
448/// Creates the menu's hand cursor sprite in window at (x, y), loading the
449/// hand's tiles into a free VRAM block. Returns the sprite, or 0 when no
450/// block is free.
452 s32 block;
453 s32 icon;
454
455 icon = 0;
456 block = Resource_FindFreeEntry();
457 if (block != 0) {
459 icon = (s32)RenderOutput_CreateFar(block, ICON_SPRITE_16X16, window, x, y);
460 }
461 return icon;
462}
463
464/// Shows a menu icon at its stored position, without rotation or scaling.
465void UiIcon_PrepareObject(struct RenderOutput *object) {
466 if (object != NULL) {
467 object->active = ICON_SHOWN;
468 object->oam.x = object->x;
469 object->oam.y = object->y;
470 object->oam.matrix = 0;
471 object->oam.affineMode = 0;
472 }
473}
474
475/// Loads the graphics of character unit into menu entry slot 0. The calling
476/// menu argument is not used.
477void PsynergyMenu_CallIconRoutineWithValue(const void *unused, s32 unit) {
479}
480
481/// Opens the menu's top-left window (13 by 5 tiles) and puts the hand cursor
482/// in it, hidden for now. Selects no tab yet. Returns the window.
483struct UiWindow *UiMenu_CreateCursor(void *source) {
484 struct PsynergyMenuState *work = source;
485 struct UiWindow *window;
486 s32 zero = 0;
487 s32 sentinel;
488 struct RenderOutput *cursor;
489
490 work->auxiliaryWindow = NULL;
491 UiWindow_UpdateOrCreate(&work->auxiliaryWindow, zero, zero, 13, 5, 2);
492 window = work->auxiliaryWindow;
493 cursor =
494 (struct RenderOutput *)UiIcon_CreateWithResourceVariant(window, -8, 11);
495 cursor->active = ICON_HIDDEN;
496 work->tabIndex[0] = 255;
497 work->tabIndex[1] = zero;
498 work->paneIcon[0] = cursor;
499 sentinel = 254;
500 cursor->sentinel = sentinel;
501 sentinel -= 255;
502 work->paneIcon[1]->sentinel = sentinel; // -1
503 return window;
504}
505
506/// Creates a walking figure for each active party member, side by side under
507/// the window source: origin (originX, originY) in tiles from the window's
508/// corner, each figure 16 + spacing pixels after the last, at full scale.
509/// Clears the unused figure slots and starts the callback that places them
510/// every frame.
511void PsynergyMenu_InitializeEntryObjects(void *source, s32 originX, s32 originY,
512 s32 spacing, s32 unused) {
513 u16 ownerIds[14];
514 struct PsynergyMenuState *menu = gMenuWork;
515 struct UiWindow *window = source;
516 s32 ownerCount = (u16)Party_ListActiveOwnersFar(ownerIds);
517 s32 i;
518
519 menu->tabCounts[0] = ownerCount;
520 // Create and position the figures before scheduling their updates.
521 for (i = 0; i < ownerCount; i++) {
522 struct AnimationObject *figure =
524 if (figure != 0) {
525 s32 offsetX;
526 s32 windowX;
527 s32 tileX;
528
529 menu->tabObjects[i] = figure;
530 windowX = window->x;
531 offsetX = spacing + 16;
532 offsetX *= i;
533 tileX = originX + windowX;
534 menu->tabX[i] = tileX * 8 + offsetX;
535 menu->rowPositions[i] = (originY + window->y) * 8 + 16;
536 menu->ownerScale[i] = 0x10000; // 1.0 in 16.16
537 figure->image.priority = 0;
538 figure->flags = 0;
540 }
541 }
542 // Clear the unused party slots so the callback can skip them.
543 for (; i < 8; i++) {
544 menu->tabObjects[i] = 0;
545 }
546 {
547 s32 priority = 200;
548 priority <<= 4;
550 }
551}
552
553/// Releases the party figures PsynergyMenu_InitializeEntryObjects created and
554/// stops their placement callback.
556 u16 ownerIds[14];
557 struct PsynergyMenuState *menu = gMenuWork;
558 s32 count;
559 struct AnimationObject **figures;
560 s32 i;
561
563 if (count != 0) {
564 figures = menu->tabObjects;
565 i = count;
566 do {
567 struct AnimationObject *figure = *figures++;
568
569 if (figure != 0) {
571 }
572 } while (--i != 0);
573 }
575}
576
577/// Scheduler callback: each frame, places every party member sprite created by
578/// PsynergyMenu_InitializeEntryObjects at its menu position and scale, through
579/// the field's projected placement.
581 struct PsynergyMenuState *menu = gMenuWork;
582 struct SpriteScale scale;
583 struct SpritePlacement position;
584 s32 i;
585 s32 count;
586
588 for (i = 0; i < count; i++) {
589 struct AnimationObject *figure = menu->tabObjects[i];
590 // 482 less the row's screen y, in 16.16.
591 s32 placeY = 0x01e20000 - (menu->rowPositions[i] << 16);
592
593 if (figure != 0) {
594 figure->image.priority = 0;
595 scale.x = menu->ownerScale[i];
596 scale.y = menu->ownerScale[i];
597 position.x = menu->tabX[i] << 16;
598 position.height = placeY;
599 position.y = (menu->rowPositions[i] << 16) + placeY; // always 482
600 position.groundHeight = 0;
601 Object_ApplyProjectedPlacementFar(figure, &position, &scale, 0x4000);
602 }
603 }
604}
605
606/// The cursor bobs through an 8-step table, one step every two frames.
607#define CURSOR_BOB_STEP() ((gFrameCount >> 1) & 7)
608
609/// Places the hand cursor at (xOffset, yOffset) inside the menu's top-left
610/// window, bobbing.
611void UiMenu_PositionCursor(s32 xOffset, s32 yOffset) {
612 struct PsynergyMenuState *work = gMenuWork;
613 struct RenderOutput *cursor = work->paneIcon[0];
614
615 cursor->oam.x = cursor->x = gUiMenu_CursorBobX[CURSOR_BOB_STEP()] + xOffset +
616 (work->auxiliaryWindow)->x * 8 + 8;
617 cursor->oam.y = cursor->y = gUiMenu_CursorBobY[CURSOR_BOB_STEP()] + yOffset +
618 (work->auxiliaryWindow)->y * 8 + 8;
619}
620
621/// Slides the hand cursor from where it is to (x, y) inside the menu's
622/// top-left window over two frames, in 1/16 pixel steps. Positions carry a
623/// 64-pixel bias while moving so that they stay positive. Does nothing, once,
624/// after skipSlide is set.
626
627 struct PsynergyMenuState *work = gMenuWork;
628 struct RenderOutput *cursor;
629 s32 steps;
630 s32 startX;
631 s32 startY;
632 s32 fineX;
633 s32 fineY;
634 s32 stepX;
635 s32 stepY;
636
637 steps = 2;
638 if (work->skipSlide != 0) {
639 work->skipSlide = 0;
640 return;
641 }
642 cursor = work->paneIcon[0];
643 {
644 s32 biasedX = cursor->oam.x + 64;
645 s32 biasedY = cursor->oam.y + 64;
646
647 cursor->x = biasedX;
648 cursor->y = biasedY;
649 }
650 x += 64;
651 y += 64;
652 if (cursor->x - 8 > 0)
653 cursor->x -= 8;
654 fineY = cursor->y;
655 if (fineY - 8 > 0) {
656 cursor->y -= 8;
657 fineY = cursor->y;
658 }
659 startX = cursor->x << 4;
660 stepX = ((x << 4) - startX + 1) / steps;
661 startY = fineY << 4;
662 stepY = ((y << 4) - startY + 1) / steps;
663 fineX = startX;
664 fineY = startY;
665 do {
666 // 64 - 8 = 56: the bias less the window border.
667 fineX += stepX;
668 cursor->oam.x = cursor->x =
669 (fineX >> 4) + ((work->auxiliaryWindow)->x << 3) - 56;
670 fineY += stepY;
671 cursor->oam.y = cursor->y =
672 (fineY >> 4) + ((work->auxiliaryWindow)->y << 3) - 56;
673 steps--;
674 if (steps != 0)
675 WaitFrames(1);
676 } while (steps != 0);
677}
678
679/// Nothing calls it.
681
682/// Lays the entry icons out eight to a row from (108, 40). Nothing calls it.
685}
686
687/// Lays the menu's entry icons (up to 32) out in a grid of 16x16 cells,
688/// columns wide, from (originX, originY); empty slots keep their place.
689void PsynergyMenu_RefreshOwnerEntries(s32 originX, s32 originY, s32 columns) {
690 struct RenderOutput **slot;
691 struct RenderOutput **scan;
692 s32 index;
693
694 index = 0;
695 slot = ((struct PsynergyMenuState *)gMenuWork)->entryIcons;
696 scan = slot;
697 do {
698 if (*scan++ != NULL) {
699 PsynergyMenu_PositionOwnerEntry(slot, index, originX, originY, columns);
700 }
701 index++;
702 slot++;
703 } while (index < 32);
704}
705
706/// Places the icon in *slot at grid cell index (0 above 31) of a grid of
707/// 16x16 cells, columns wide, from (originX, originY), and shows it.
709 s32 originX, s32 originY, s32 columns) {
710 struct RenderOutput *icon;
711
712 if (index > 31) {
713 index = 0;
714 }
715 icon = *slot;
716 icon->y = (index / columns) * 16 + originY;
717 icon->x = (index % columns) * 16 + originX;
719}
720
721/// Places the icon at slotIndex (0 above 15) in a columns-wide grid of
722/// 24x16 cells starting at (originX, originY), and shows it.
723void ItemMenu_PlaceIcon(struct RenderOutput **slot, s32 slotIndex, s32 originX,
724 s32 originY, s32 columns) {
725 struct RenderOutput *icon;
726
727 if (slotIndex > 15)
728 slotIndex = 0;
729 icon = *slot;
730 icon->y = slotIndex / columns * 16 + originY;
731 icon->x = slotIndex % columns * 24 + originX;
733}
734
735/// Lays the inventory's 15 item icons out five to a row from (116, y): y is
736/// 56 for layout 1 and 40 otherwise.
738 struct RenderOutput **slot;
739 struct RenderOutput **scan;
740 struct RenderOutput *icon;
741 s32 index;
742 s32 originY;
743 struct InventoryMenuState *menu;
744
745 menu = gMenuWork;
746 originY = 56;
747 if (layout != 1) {
748 originY = 40;
749 }
750 slot = menu->entryIcons;
751 index = 0;
752 scan = slot;
753 do {
754 icon = *scan++;
755 if (icon != NULL) {
756 ItemMenu_PlaceIcon(slot, index, 116, originY, MENU_ITEM_GRID_COLUMNS);
757 }
758 index++;
759 slot++;
760 } while (index < 15);
761}
762
763/// Shows message in the item menu, with the hand cursor hidden meanwhile.
764///
765/// With y == -1 the message goes into the info window; otherwise a modal
766/// window sized to the message opens at (x, y). With x == -1 the message stays
767/// up and FLAG_MENU_INFO_KEPT records that the info window holds it (the next
768/// selection keeps it instead of drawing the item name); otherwise it waits
769/// for A, B or Start and clears it again.
771 struct InventoryMenuState *menu = gMenuWork;
772 struct UiWindow *window;
773 s32 height;
774 s32 width;
775 s32 top;
776 s32 left;
777
778 menu->paneIcons[0]->active = ICON_HIDDEN;
779 if (y != -1) {
780 UiText_GetResourceDimensionsFar(message, &left, &top, &width, &height);
782 WINDOW_KEEP_EXISTING | 2) == 0)
784 window = menu->modalWindow;
785 } else {
786 window = menu->infoWindow;
787 }
789 RenderOutput_ClearListFar((void *)window);
790#if TBS_PATCH_1
791 if (y == -1)
792 UiText_DrawCharacterAtOffsetFar(message, window, 0, 0);
793 else
794 UiText_DrawResourceFar(message, window, 0, 0);
795#else
796 UiText_DrawResourceFar(message, window, 0, 0);
797#endif
798 if (x != -1) {
799 WaitFrames(1);
800 do {
801 WaitFrames(1);
802 } while (!(gKeysPressed & KEY_A) && !(gKeysPressed & KEY_B) &&
804#if TBS_PATCH_1
805 if (y == -1)
807#endif
808 RenderOutput_ClearListFar((void *)window);
809 } else {
811 }
812 menu->completionFlag = 1;
813 menu->paneIcons[0]->active = ICON_SHOWN;
814#if TBS_PATCH_1
815 if (y != -1)
817#endif
818}
819
820/// Sorts a party member's 15 inventory slots by the list order of mode (see
821/// Menu_CopyListOrder): items are grouped by the order's item types and, within
822/// a type, run from the highest item id down. Empty slots go to the end.
823/// L + A in the item menu cycles through the modes. Returns 1.
825 u16 sorted[16];
826 u16 items[16];
827 u8 order[32];
828 struct ItemDefinition *item;
829 s32 pass;
830 s32 i;
831 s32 count;
832 s32 best;
833 s32 bestSlot;
834 s32 sortedCount;
835 s32 value;
836
837 bestSlot = 0;
838 sortedCount = 0;
839 Menu_CopyListOrder(mode, order);
840
841 for (i = 0; i < 15; i++)
842 items[i] = inventory[i];
843
844 count = 0;
845 for (i = 0; i < 15; i++) {
846 if (items[i] != 0)
847 count++;
848 }
849
850 for (i = count; i < 15; i++)
851 sorted[i] = 0;
852
853 // One pass for each entry of the order: move its items across, the highest
854 // id first, until none is left.
855 pass = 0;
856 while (order[pass] != LIST_ORDER_END) {
857 for (;;) {
858 best = 0;
859 for (i = 0; i < count; i++) {
860 if (items[i] == 0)
861 continue;
862 item = Item_GetDirectFar(items[i]);
863 if ((order[pass] & LIST_ORDER_TYPE_MASK) != item->type)
864 continue;
865 if ((order[pass] & LIST_ORDER_EQUIPPED) &&
866 (items[i] & INVENTORY_EQUIPPED) == 0)
867 continue;
868 value = items[i] & ITEM_ID_MASK;
869 if (best < value) {
870 bestSlot = i;
871 best = value;
872 }
873 }
874 if (best == 0)
875 break;
876 sorted[sortedCount] = items[bestSlot];
877 items[bestSlot] = 0;
878 sortedCount++;
879 }
880 pass++;
881 }
882
883 for (i = 0; i < count; i++)
884 inventory[i] = sorted[i];
885 return 1;
886}
887
888/// Copies the list order of mode 0 to 2 (any other mode: the default order)
889/// into order, up to and including its LIST_ORDER_END and at most 32 bytes.
890void Menu_CopyListOrder(s32 mode, u8 *order) {
891 u8 *src;
892 s32 n;
893
895 switch (mode) {
896 case 0:
898 break;
899 case 1:
901 break;
902 case 2:
904 break;
905 }
906 *order = *src;
907 n = 0;
908 if (*order != LIST_ORDER_END) {
909 do {
910 if (++n > 31)
911 break;
912 src++;
913 order++;
914 *order = *src;
915 } while (*order != LIST_ORDER_END);
916 }
917}
918
919/// The page indicator: the window font's digit tiles for pages 1, 2, ...,
920/// between the two page arrows.
921#define PAGE_LABEL_FIRST 49
922
923/// Moves a paged list's cursor and page with the d-pad's repeating keys.
924///
925/// count entries are shown pageSize at a time; *cursor is the row on the page
926/// and *page the page. Vertical lists (horizontal 0) move the cursor with Up
927/// and Down and turn pages with Left and Right; horizontal lists the other way
928/// round. Moving past either end wraps round; turning to a shorter page pulls
929/// the cursor up to its last entry. Returns 1 after a page turn, 0 after a
930/// cursor move and -1 when nothing moved or the list is empty.
931s32 Menu_HandlePageInput(s32 horizontal, s32 count, s32 pageSize, s32 *cursor,
932 s32 *page) {
933 s32 pages;
934 s32 next;
935 s32 previous;
936 s32 pageForward;
937 s32 result;
938
939 result = -1;
940 if (count == 0)
941 return result;
942 // Animate the page arrows.
944 pages = count / pageSize;
945 if (count % pageSize != 0)
946 pages++;
947 // horizontal is reused for the page-back key.
948 if (horizontal) {
949 next = gKeysRepeat & KEY_RIGHT;
950 previous = gKeysRepeat & KEY_LEFT;
951 horizontal = gKeysRepeat & KEY_UP;
952 pageForward = gKeysRepeat & KEY_DOWN;
953 } else {
954 next = gKeysRepeat & KEY_DOWN;
955 previous = gKeysRepeat & KEY_UP;
956 horizontal = gKeysRepeat & KEY_LEFT;
957 pageForward = gKeysRepeat & KEY_RIGHT;
958 }
959 if (horizontal) {
961 if (--*page < 0)
962 *page = pages - 1;
963 if (*cursor + *page * pageSize > count - 1) {
964 *cursor = count - *page * pageSize - 1;
965 if (*cursor > pageSize - 1)
966 *cursor = pageSize - 1;
967 }
969 result = 1;
970 return result;
971 }
972 if (pageForward) {
974 if (++*page > pages - 1)
975 *page = 0;
976 if (*cursor + *page * pageSize > count - 1) {
977 *cursor = count - *page * pageSize - 1;
978 if (*cursor > pageSize - 1)
979 *cursor = pageSize - 1;
980 }
982 result = 1;
983 return result;
984 }
985 if (previous) {
987 if (--*cursor < 0) {
988 *cursor = pageSize - 1;
989 *cursor = count - *page * pageSize - 1;
990 if (*cursor > pageSize - 1)
991 *cursor = pageSize - 1;
992 }
993 return 0;
994 }
995 result = -1;
996 if (next == 0)
997 return result;
998 {
1000 result = 0;
1001 if (++*cursor == count - *page * pageSize)
1002 *cursor = result;
1003 if (*cursor > pageSize - 1)
1004 *cursor = result;
1005 }
1006 return 0;
1007}
1008
1009/// Copies the last background palette (15) into background palette bank and
1010/// lightens its colour 4 by 9 steps in each channel: the highlight colour of
1011/// the menu's selected rows.
1013 u16 *palette = (u16 *)&BG_PLTT_COLOR(bank, 0);
1014 u32 red;
1015 u32 green;
1016 u32 blue;
1017
1018 Dma_Set((const void *)&BG_PLTT_COLOR(15, 0), palette, DMA_ENABLE << 16 | 16,
1019 REG_DMA3);
1020 Dma_Set((const void *)&BG_PLTT_COLOR(15, 0), palette,
1021 (DMA_ENABLE | DMA_32BIT) << 16 | 8, REG_DMA3);
1022 blue = palette[4] >> 10;
1023 green = (palette[4] >> 5) & 31;
1024 red = palette[4] & 31;
1025 blue += 9;
1026 if (blue > 31)
1027 blue = 31;
1028 green += 9;
1029 if (green > 31)
1030 green = 31;
1031 red += 9;
1032 if (red > 31)
1033 red = 31;
1034 palette[4] = (blue << 10) | (green << 5) | red;
1035}
1036
1037/// Draws a paged list's page numbers on the top border of window, ending at
1038/// tile rightEdge: one digit per page between the page arrows, selectedPage in
1039/// palette 14 and the others in palette 15. Draws nothing for a single page.
1040void Menu_DrawPageIndicator(struct UiWindow *window, s32 itemCount,
1041 s32 pageSize, s32 selectedPage, s32 rightEdge) {
1042 s32 pageCount;
1043 s32 page;
1044 s32 x;
1045 s32 tile;
1046
1047 x = rightEdge;
1048 tile = PAGE_LABEL_FIRST;
1049 pageCount = itemCount / pageSize;
1050 if (itemCount % pageSize != 0)
1051 pageCount++;
1052
1053 x -= pageCount;
1054 if (pageCount > 1) {
1055 UiWindow_SetTilemapEntryFar(window, UI_PAGE_ARROW_LEFT, x - 1, -1, 0);
1056
1057 for (page = 0; page < pageCount; page++) {
1058 if (page == selectedPage)
1059 UiWindow_SetTilemapEntryFar(window, tile, x, -1, 2); // palette 14
1060 else
1061 UiWindow_SetTilemapEntryFar(window, tile, x, -1, 3); // palette 15
1062 tile++;
1063 x++;
1064 }
1065
1067 }
1068}
1069
1070/// Switches a rectangle of a window's text between palette 15 (normal) and 14
1071/// (the highlight made by Palette_LightenBankHighlight): palette is the new
1072/// palette number. Only bit 12 of each map entry is cleared before it is set,
1073/// so this works between those two palettes. (x, y) and the size are in tiles
1074/// inside the window's border; the rectangle is clipped to the screen.
1075void Render_SetTilemapFlagRect(const struct UiWindow *window, s32 x, s32 y,
1076 s32 width, s32 height, u32 palette) {
1077 struct UiRenderWork *work = (struct UiRenderWork *)gWindowWork[0];
1078 u8 *tilemap = (u8 *)work->tilemap;
1079
1080 x += window->x + 1;
1081 y += window->y + 1;
1082 palette <<= 12;
1083 if (x < 0) {
1084 width += x;
1085 x = 0;
1086 }
1087 if (x + width > 29) {
1088 width = 30 - x;
1089 }
1090 if (y < 0) {
1091 height += y;
1092 y = 0;
1093 }
1094 if (y + height > 29) {
1095 height = 20 - y;
1096 }
1097 if (width > 0 && height > 0) {
1098 // Byte offset of the first entry: 32 two-byte entries a row.
1099 y <<= 6;
1100 x = y + (x << 1);
1101 do {
1102 u16 *entry = (u16 *)(x + (u32)tilemap);
1103 s32 remaining = width;
1104 while (remaining != 0) {
1105 u32 value = *entry;
1106 value &= 0xFFFFEFFF;
1107 value |= palette;
1108 remaining--;
1109 *entry = value;
1110 entry++;
1111 }
1112 height--;
1113 x += 64;
1114 } while (height != 0);
1115 work->dirty = 1;
1116 }
1117}
1118
1119/// Copies the first sprite palette into background palette 14, then colour 4
1120/// of background palette 15 over its colour 14.
1122 Dma_Set((const void *)OBJ_PLTT, (void *)&BG_PLTT_COLOR(14, 0),
1123 DMA_ENABLE << 16 | 16, REG_DMA3);
1124 Dma_Set((const void *)&BG_PLTT_COLOR(15, 4), (void *)&BG_PLTT_COLOR(14, 14),
1125 DMA_ENABLE << 16 | 1, REG_DMA3);
1126}
1127
1128/// Shows the item icons of one page of the item list: entries first to
1129/// first + pageSize - 1, one row of 16 pixels each from (x, y). Hides all the
1130/// others.
1131void Menu_SetPageIcons(s32 pageSize, s32 first, struct UiWindow *window, s32 x,
1132 s32 y) {
1133 struct InventoryMenuState *menu = gMenuWork;
1134 struct RenderOutput *icon;
1135 s32 i;
1136
1137 for (i = 0; i < 32; i++) {
1138 icon = menu->entryIcons[i];
1139 if (icon != NULL)
1140 icon->active = ICON_HIDDEN;
1141 }
1142 for (i = first;
1143 i < pageSize + first && (icon = menu->entryIcons[i]) != NULL &&
1144 i <= menu->itemCount - 1;
1145 i++) {
1146 icon->x = x;
1147 icon->y = y + (i - first) * 16;
1149 icon->active = ICON_SHOWN;
1150 }
1151}
1152
1153/// Writes the party's coins and the "Coins" label into window.
1156 UiText_DrawCharacterAtOffsetFar(MsgCoinsLabel, window, 64, 0);
1157#if !TBS_PATCH_1
1158 UiWindow_DrawDividerLineFar(window, 12, 0, 12, 2);
1159#endif
1160}
1161
1162/// Moves and resizes a window, in tiles.
1163void UiWindow_SetBounds(struct UiWindow *window, s32 x, s32 y, s32 width,
1164 s32 height) {
1165 if (window != NULL) {
1166 window->width = width;
1167 window->x = x;
1168 window->height = height;
1169 window->y = y;
1170 }
1171}
1172
1174 ((struct UiRenderWork *)gWindowWork[0])->menuBusy = 1;
1175}
1176
1177/// Lets the window renderer resume drawing after a menu update.
1179 ((struct UiRenderWork *)gWindowWork[0])->menuBusy = 0;
1180}
1181
1184 return 1;
1185}
1186
1187/// Scheduler callback while a menu runs: on Start, plays the cancel sound,
1188/// sets FLAG_MENU_START_PRESSED and removes itself.
1190 if (gKeysPressed & KEY_START) {
1194 }
1195}
1196
1197/// Starts watching for Start: clears FLAG_MENU_START_PRESSED and adds
1198/// Menu_CancelSoundTick.
1202}
1203
1204/// Stops watching for Start, if Start has not removed the watch already.
1208 }
1209}
1210
1211/// Sets the window text colour: normal (15), no HP (2) and low HP (4).
1213
1215
1217
1218#undef STATUS_PANEL_TEXT_X
1219#undef STATUS_PANEL_CANNOT_EQUIP_X
1220#undef STATUS_PANEL_LEARN_NAME_Y
1221#undef STATUS_PANEL_LEARN_STATUS_Y
1222#undef WINDOW_KEEP_EXISTING
1223#undef WINDOW_STYLE_MASK
1224#undef NUMBER_PIXELS_PER_DIGIT
1225#undef ICON_TILE_BYTES
1226#undef CURSOR_BOB_STEP
1227#undef PAGE_LABEL_FIRST
@ OWNER_ACTION_ID_MASK
Definition battle_unit.h:14
@ CHARACTER_HAUNT
@ CHARACTER_CURSE
@ CHARACTER_POISON
@ CHARACTER_VENOM
void UiMenu_SlideCursor(s32 x, s32 y)
Slides the hand cursor from where it is to (x, y) inside the menu's top-left window over two frames,...
Definition common.c:625
void PsynergyMenu_PositionOwnerEntry(struct RenderOutput **slot, s32 index, s32 originX, s32 originY, s32 columns)
Places the icon in *slot at grid cell index (0 above 31) of a grid of 16x16 cells,...
Definition common.c:708
#define WINDOW_STYLE_MASK
Definition common.c:33
void Menu_ReleaseEntryObjects(void)
Releases the party figures PsynergyMenu_InitializeEntryObjects created and stops their placement call...
Definition common.c:555
struct UiWindow * UiMenu_CreateCursor(void *source)
Opens the menu's top-left window (13 by 5 tiles) and puts the hand cursor in it, hidden for now.
Definition common.c:483
s32 InventoryMenu_SortByListOrder(u16 *inventory, s32 mode)
Sorts a party member's 15 inventory slots by the list order of mode (see Menu_CopyListOrder): items a...
Definition common.c:824
#define PAGE_LABEL_FIRST
The page indicator: the window font's digit tiles for pages 1, 2, ..., between the two page arrows.
Definition common.c:921
void UiText_DrawStatComparison(const struct BattleUnit *after, const struct BattleUnit *before, struct UiWindow *window)
Writes Attack, Defense and Agility into a status window as they are now (before), and beside each one...
Definition common.c:394
#define WINDOW_KEEP_EXISTING
UiWindow_UpdateOrCreate: keep an existing window as it is, without redrawing its saved rectangle.
Definition common.c:32
UNUSED void PsynergyMenu_ReservedNoOp(void)
Nothing calls it.
Definition common.c:680
void UiIcon_PrepareObject(struct RenderOutput *object)
Shows a menu icon at its stored position, without rotation or scaling.
Definition common.c:465
void UiText_DrawWorkValueWithLabel(struct UiWindow *window)
Writes the party's coins and the "Coins" label into window.
Definition common.c:1154
#define NUMBER_PIXELS_PER_DIGIT
The pixels the field allows each digit.
Definition common.c:275
void Palette_LightenBankHighlight(s32 bank)
Copies the last background palette (15) into background palette bank and lightens its colour 4 by 9 s...
Definition common.c:1012
#define STATUS_PANEL_LEARN_NAME_Y
Definition common.c:26
void PsynergyMenu_CallIconRoutineWithValue(const void *unused, s32 unit)
Loads the graphics of character unit into menu entry slot 0.
Definition common.c:477
#define ICON_TILE_BYTES
Size of one 16x16 4bpp sprite tile block.
Definition common.c:430
void UiPalette_SetColor2(void)
Definition common.c:1214
void Menu_UpdateEntryObjectTransforms(void)
Scheduler callback: each frame, places every party member sprite created by PsynergyMenu_InitializeEn...
Definition common.c:580
void Render_SetTilemapFlagRect(const struct UiWindow *window, s32 x, s32 y, s32 width, s32 height, u32 palette)
Switches a rectangle of a window's text between palette 15 (normal) and 14 (the highlight made by Pal...
Definition common.c:1075
void PsynergyMenu_RefreshOwnerEntries(s32 originX, s32 originY, s32 columns)
Lays the menu's entry icons (up to 32) out in a grid of 16x16 cells, columns wide,...
Definition common.c:689
s32 UiIcon_CreateWithResourceVariant(struct UiWindow *window, s32 x, s32 y)
Creates the menu's hand cursor sprite in window at (x, y), loading the hand's tiles into a free VRAM ...
Definition common.c:451
#define STATUS_PANEL_TEXT_X
Definition common.c:13
void ItemMenu_PlaceIcon(struct RenderOutput **slot, s32 slotIndex, s32 originX, s32 originY, s32 columns)
Places the icon at slotIndex (0 above 15) in a columns-wide grid of 24x16 cells starting at (originX,...
Definition common.c:723
void Palette_CopyObjectBankToBackground14(void)
Copies the first sprite palette into background palette 14, then colour 4 of background palette 15 ov...
Definition common.c:1121
void UiWork_SetMenuBusy(void)
Definition common.c:1173
StatArrow
The stat arrows: the up and down arrow sprites the menu loads into its two resource slots (Resource_L...
Definition common.c:389
@ STAT_ARROW_UP
Definition common.c:389
@ STAT_ARROW_DOWN
Definition common.c:389
void Menu_DrawPageIndicator(struct UiWindow *window, s32 itemCount, s32 pageSize, s32 selectedPage, s32 rightEdge)
Draws a paged list's page numbers on the top border of window, ending at tile rightEdge: one digit pe...
Definition common.c:1040
static s32 CountDigitsAtLeastTwo(s32 number)
Returns how many decimal digits number has, but at least 2: 0-99 give 2, 100-999 give 3,...
Definition common.c:282
void UiMenu_PositionCursor(s32 xOffset, s32 yOffset)
Places the hand cursor at (xOffset, yOffset) inside the menu's top-left window, bobbing.
Definition common.c:611
#define STATUS_PANEL_LEARN_STATUS_Y
Definition common.c:27
void ItemMenu_RefreshEntry(s32 layout)
Lays the inventory's 15 item icons out five to a row from (116, y): y is 56 for layout 1 and 40 other...
Definition common.c:737
static void Owner_Copy(struct BattleUnit *destination, struct BattleUnit *source)
Copies one BattleUnit with the resident IWRAM word copy.
Definition common.c:106
UNUSED s32 UiIcon_CreateWithResource(struct UiWindow *window, s32 unused, s32 x, s32 y)
Creates a hand cursor sprite in window at (x, y), loading the hand's tiles into a free VRAM block.
Definition common.c:435
#define STATUS_PANEL_CANNOT_EQUIP_X
Definition common.c:14
void Menu_CancelSoundReset(void)
Starts watching for Start: clears FLAG_MENU_START_PRESSED and adds Menu_CancelSoundTick.
Definition common.c:1199
void UiWindow_SetBounds(struct UiWindow *window, s32 x, s32 y, s32 width, s32 height)
Moves and resizes a window, in tiles.
Definition common.c:1163
s32 Menu_SuspendFieldTasks(void)
Suspends the overlay tasks and tile animations while a menu is open, and sets flags 0x152 and 0x166.
Definition common.c:52
void UiWindow_CloseIfOpen(struct UiWindow **handle, s32 style)
Closes the window kept in *handle, if any, and clears the handle.
Definition common.c:98
void UiWindow_InitializeWork(s32 unused)
Clears the whole menu work and sets its defaults: no pane selected, one entry in each pane,...
Definition common.c:61
void UiPalette_SetColor4(void)
Definition common.c:1216
#define CURSOR_BOB_STEP()
The cursor bobs through an 8-step table, one step every two frames.
Definition common.c:607
void Menu_CopyListOrder(s32 mode, u8 *order)
Copies the list order of mode 0 to 2 (any other mode: the default order) into order,...
Definition common.c:890
void UiWork_ClearMenuBusy(void)
Lets the window renderer resume drawing after a menu update.
Definition common.c:1178
void UiPalette_SetColor15(void)
Sets the window text colour: normal (15), no HP (2) and low HP (4).
Definition common.c:1212
void PsynergyMenu_InitializeEntryObjects(void *source, s32 originX, s32 originY, s32 spacing, s32 unused)
Creates a walking figure for each active party member, side by side under the window source: origin (...
Definition common.c:511
void Menu_EnsureCancelSound(void)
Stops watching for Start, if Start has not removed the watch already.
Definition common.c:1205
s32 Menu_ResumeFieldTasks(void)
Resumes the overlay tasks and tile animations when a menu closes, and clears game flags 0x166 and 0x1...
Definition common.c:38
void Menu_DrawOwnerStatusPanel(struct UiWindow *unused, s32 owner, s32 slot, s32 mode)
Draws the item menu's status panel for the party member owner (window at tile 0,5,...
Definition common.c:117
void Ui_DrawValuePairRows(struct BattleUnit *unit, struct UiWindow *window)
Draws a character's HP and PP into window as two rows, "HP current/maximum" at pixel row 40 and "PP c...
Definition common.c:333
void InventoryMenu_ShowModalMessage(s32 message, s32 x, s32 y)
Shows message in the item menu, with the hand cursor hidden meanwhile.
Definition common.c:770
void Menu_CancelSoundTick(void)
Scheduler callback while a menu runs: on Start, plays the cancel sound, sets FLAG_MENU_START_PRESSED ...
Definition common.c:1189
s32 Menu_HandlePageInput(s32 horizontal, s32 count, s32 pageSize, s32 *cursor, s32 *page)
Moves a paged list's cursor and page with the d-pad's repeating keys.
Definition common.c:931
UNUSED void PsynergyMenu_RefreshOwnerEntriesDefault(void)
Lays the entry icons out eight to a row from (108, 40). Nothing calls it.
Definition common.c:683
void UiText_DrawNumberRightAligned(s32 number, struct UiWindow *window, s32 x, s32 y)
Draws number right-aligned in a field that ends at pixel column x and allows 8 pixels for each digit,...
Definition common.c:316
s32 Audio_PlayCueReturnOne(s32 cue)
Definition common.c:1182
void Menu_SetPageIcons(s32 pageSize, s32 first, struct UiWindow *window, s32 x, s32 y)
Shows the item icons of one page of the item list: entries first to first + pageSize - 1,...
Definition common.c:1131
s32 UiWindow_UpdateOrCreate(struct UiWindow **handle, s32 x, s32 y, s32 w, s32 h, s32 flags)
Opens the window kept in *handle, or redraws it if it is already open.
Definition common.c:78
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
Definition dma.h:62
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
Definition dma.h:30
void MapAnimation_SuspendFar(void)
s32 AnimationObjects_SelectAnimationFar(struct AnimationObject *state, s32 flags)
struct AnimationObject * ResourceObject_CreateFar(s32 id)
void MapAnimation_ResumeFar(void)
void Object_ApplyProjectedPlacementFar(struct AnimationObject *sprite, const struct SpritePlacement *position, const struct SpriteScale *scale, s32 facing)
Far call to Render_ApplyProjectedPlacement.
void ResourceObject_ReleaseFar(struct AnimationObject *sprite)
struct BattleUnit * UnitGetFar(u32 owner)
struct ItemDefinition * Item_GetDirectFar(s32 item)
s32 Party_ListActiveOwnersFar(s16 *owners)
s32 GameFlag_TestFar(s32 flag)
s32 GameFlag_SetBitFar(s32 flag)
s32 Inventory_EquipFar(s32 owner, s32 slot)
s32 Item_CanOwnerEquip(s32 unit, s32 item)
Far call to Item_CanOwnerEquipDirect.
s32 Party_CountActiveOwnersFar(void)
void GameFlag_ClearBitFar(s32 flag)
void UnitCalcFar(s32 owner)
s32 Party_RemapCharacterIdByFlagsFar(s32 arg0)
void AudioCommand_PlayFar(s32 id)
void Ui_LoadCharacterEntryForSlotFar(u32 slot, s32 character, s32 value)
struct UiWindow * UiWindow_CreateFar(s32 x, s32 y, s32 width, s32 height, s32 attrs)
void RenderOutput_ClearListFar(void *work)
void UiText_DrawNumberInWindowFar(s32 arg0, s32 arg1, struct UiWindow *arg2, s32 arg3, s32 arg4)
void UiWork_SetParamNibbleFar(s32 param)
s32 UiText_GetResourceDimensionsFar(s32 no, s32 *x, s32 *y, u32 *width, u32 *height)
void Link_DrawShiftedTilePairFar(s32 offset)
struct RenderOutput * SideObject_CreateFar(s32 object_kind, s32 position, s32 side, struct UiWindow *arg3, s32 arg4, s32 arg5)
Far call to CreateSideObject.
void UiText_DrawNumberAtOffsetFar(s32 arg0, s32 arg1, const struct UiWindow *arg2, s32 arg3, s32 arg4)
void UiWindow_ClearInteriorTilesFar(const struct UiWindow *window, u32 left, u32 top, u32 right, u32 bottom)
void UiWindow_DrawDividerLineFar(struct UiWindow *win, u32 x1, u32 y1, u32 x2, u32 y2)
void UiText_DrawCharacterAtOffsetFar(s32 character, const struct UiWindow *position, u32 offsetX, u32 offsetY)
struct RenderOutput * RenderOutput_CreateFar(s32 slot, s32 flags, struct UiWindow *input, s32 offsetX, s32 offsetY)
void UiText_DrawResourceFar(s32 arg0, struct UiWindow *arg1, s32 arg2, s32 arg3)
void UiWork_FinalizeFar(struct UiWindow *work, s32 release)
void UiText_DrawStringAtOffsetFar(const u8 *text, const struct UiWindow *work, s32 offsetX, s32 offsetY)
void UiWindow_SetTilemapEntryFar(struct UiWindow *window, s32 value, s32 x, s32 y, u32 mode)
void RenderOutput_RedrawSavedRectFar(struct UiWindow *window)
void UiText_DrawStringInWindowFar(const u8 *text, struct UiWindow *arg1, u32 x, u32 y)
void Input_ResetKeyRepeat(void)
Restarts the key repeat delay, so held keys wait the full delay again.
Definition frame.c:289
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
struct GameState gGameState
void * gMenuWork
const u8 gUi_SlashString[]
const u8 gUi_PpRowString[]
u8 gUiIcon_ResourceTiles[]
const u8 gUi_HpRowString[]
const u8 gUi_HpString[]
const u8 gUi_PpString[]
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
#define OBJ_PLTT
Definition io_reg.h:159
@ KEY_UP
Definition io_reg.h:249
@ KEY_B
Definition io_reg.h:244
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_START
Definition io_reg.h:246
@ KEY_RIGHT
Definition io_reg.h:247
@ KEY_A
Definition io_reg.h:243
@ KEY_DOWN
Definition io_reg.h:250
#define DMA_32BIT
Definition io_reg.h:210
#define REG_DMA3
Definition io_reg.h:153
#define BG_PLTT_COLOR(palette, color)
Definition io_reg.h:158
#define DMA_ENABLE
Definition io_reg.h:217
@ INVENTORY_EQUIPPED
Definition item.h:17
@ ITEM_ID_MASK
Definition item.h:16
volatile u32 gKeysPressed
Keys that went down this frame.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
void MemFree(void *buffer)
s32 UiIcon_CreateStatChangeArrow(struct UiWindow *window, s32 x, s32 y, s32 variant)
Creates a stat-change arrow from one of the two loaded resources.
Definition icons.c:66
s32 CharacterMenu_BuildAvailability(u8 *ailments, s32 requested, s32 ownerId)
Fills ailments[0..4] (CharacterAilment) with member ownerId's ailments: down (only when requested is ...
Definition status.c:1130
u8 gUi_LvString[]
What every part of the menu object shares: its includes, and the macros and types more than one part ...
#define TEXT_COLOR_LOW_HP
HP under a quarter of the maximum.
#define MENU_WORK_SIZE
The bytes of the menu work, heap block HEAP_SLOT_MENU.
#define ICON_HIDDEN
#define MENU_ITEM_GRID_COLUMNS
Inventory icons occupy five columns in the fifteen-slot list.
#define TEXT_COLOR_NO_HP
HP 0.
#define FLAG_MENU_INFO_KEPT
The info window holds a message the next selection must not draw over.
#define ICON_SHOWN
RenderOutput.active as the menu sets it: shown, or hidden but kept.
#define STATUS_PANEL_LOWER_ONLY
Keeps the open window, the name and the ailments, and redraws only the part below them.
#define TEXT_COLOR_NORMAL
#define ICON_SPRITE_16X16
RenderOutput_CreateFar's sprite attributes for the menu's 16x16 icons.
u8 IwramCopyWords[]
#define FLAG_MENU_START_PRESSED
Game flags of the menus.
#define MENU_DRAW_STATUS_LABEL
@ STATUS_PANEL_STATS
Attack, Defense, Agility and Luck.
@ STATUS_PANEL_LEARN
the Psynergy a Psynergy item teaches
@ STATUS_PANEL_EQUIP
stats if the item were equipped
@ STATUS_PANEL_EXPERIENCE
class, HP, PP and experience
@ STATUS_PANEL_CLASS
class, HP and PP
#define STATUS_PANEL_KIND_MASK
u8 gMenu_ListOrderDefault[11]
The item menu's sort orders (InventoryMenu_SortByListOrder), one item type per byte,...
Definition menudata.c:21
u8 gMenu_ListOrderMode2[11]
Definition menudata.c:23
u8 gMenu_ListOrderMode1[20]
Definition menudata.c:26
u8 gUiMenu_CursorBobY[9]
Definition menudata.c:13
u8 gMenu_ListOrderMode0[20]
Definition menudata.c:30
u8 gUiMenu_CursorBobX[9]
The hand cursor's bobbing offsets, indexed by (gFrameCount >> 1) & 7.
Definition menudata.c:12
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_ResumeOverlayTasks(void)
Resumes every task whose routine is in an overlay, flagged or not.
Definition scheduler.c:265
s32 Scheduler_SuspendOverlayTasks(void)
Suspends every task whose routine is in an overlay (EWRAM, 0x02xxxxxx) unless its flag bit 0 asks to ...
Definition scheduler.c:197
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
s32 _call_via_r3(s32, s32, s32, s32)
#define SE_MENU_CANCEL
Definition songs.h:106
#define SE_MENU_CURSOR_MOVE
Definition songs.h:104
#define NULL
Definition bilibin.h:6
u8 gWindowWork[]
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
s8 offsetX
pixels
Definition animspr.h:121
struct AnimationSpritePart image
Definition animspr.h:109
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
Definition animspr.h:128
u8 count
layers in use, up to the last one present
Definition animspr.h:129
s32 scale
16.16 fixed point, 0x10000 full size
Definition animspr.h:111
u16 priority
2 when created
Definition animspr.h:100
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 luck
0 to 99 (UnitCalc)
s16 maxPp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
u8 name[0x0f]
The name, one byte a character, ending in 0.
s16 hp
current HP, 0 when downed
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...
s16 maxHp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
u32 experience
a character's experience points
u8 classIndex
The character's class, worked out from its Djinn (Unit_UpdateClass); 0 marks an enemy,...
u16 atk
Attack, 0 to 999 (UnitCalc).
u8 level
1 to 99 for a character
u16 agi
Agility, 0 to 999: the order of the round's actions.
u16 def
Defense, 0 to 999 (UnitCalc).
u16 inventory[15]
Items held, one entry each: bits 15..11 quantity | 10 broken | 9 equipped | 8..0 item id (INVENTORY_*...
The item menu's work, in the HEAP_SLOT_MENU work slot: its windows, the party figures,...
struct UiWindow * modalWindow
s16 completionFlag
set to 1 as item commands end; not read by name
struct UiWindow * infoWindow
struct RenderOutput * paneIcons[2]
The two panes: the member whose items are shown, and the one an item is given to.
s8 equipPreview
1 while the stats preview a removal, not an equip
u16 flags
1 while the item's name and command grid are drawn
s8 paneCount[2]
members to choose from; 1 at first
struct RenderOutput * entryIcons[32]
s8 paneIndex[2]
the member chosen, in ownerIds; -1 for none at first
An item's definition: its price, type, who can equip it, its bonuses and unleash, its effects and the...
Definition item.h:104
u8 type
enum ItemType; 0 for an item that is not equipment
Definition item.h:106
u16 encodedAction
bits: 15 from the class | 14 from an equipped item | 13..0 action id.
Definition battle_unit.h:22
The Psynergy menu: its windows, icons and cursors, the party members' tabs and the Psynergy listed fo...
s32 ownerScale[8]
16.16 fixed point, 0x10000 full size
s8 tabCounts[2]
members each pane chooses from
struct RenderOutput * entryIcons[32]
struct RenderOutput * paneIcon[2]
each pane's cursor
s16 tabX[8]
screen pixels
u16 skipSlide
1 skips the cursor's next slide once
struct UiWindow * auxiliaryWindow
s8 tabIndex[2]
each pane's member, in ownerTable
struct AnimationObject * tabObjects[8]
the party members' figures
s16 rowPositions[8]
screen pixels
A render output: a sprite in a window's output list (a character, an icon or a portrait),...
struct RenderOam oam
u16 y
screen pixels
u8 sentinel
depth slot it is drawn at (254 for glyphs)
s8 active
its UI_SPRITE_ motion; 0 while free
u16 x
screen pixels
s8 index
VRAM cache slot, or a glyph's tile after glyphTiles.
A sprite's screen position and its two vertical offsets, in 16.16 pixels.
s32 x
screen x of the sprite's centre
s32 y
screen y at the ground; sets the depth slot
s32 groundHeight
how far the shadow is raised above y
s32 height
how far the image is raised above y
Horizontal and vertical sprite scale; 0x10000 is the original size.
The window system's work: the windows' tilemap, the windows, the three text channels,...
Definition window.h:19
u16 tilemap[640]
the windows' BG tilemap, 32 by 20 tiles
Definition window.h:20
u8 dirty
The tilemap's 4-row bands to upload: bit 0 for all, bit n + 1 for band n.
Definition window.h:32
u8 menuBusy
while set, the tilemap is not uploaded
Definition window.h:40
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 flags
UI_WINDOW_ flags; 0 once closing or free.
Definition uiwindow.h:25
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
u16 height
tiles
Definition uiwindow.h:14
u16 width
tiles
Definition uiwindow.h:13
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 UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
#define LIST_ORDER_EQUIPPED
Definition menu.h:18
#define LIST_ORDER_END
Definition menu.h:19
#define LIST_ORDER_TYPE_MASK
Definition menu.h:17
#define UI_PAGE_ARROW_RIGHT
Definition window.h:67
#define UI_PAGE_ARROW_LEFT
Definition window.h:66
#define UI_PAGE_ARROW_VRAM
Definition window.h:64
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