13#define CHARACTER_SELECTOR_OWNER_COUNT 8
15#define CHARACTER_SELECTOR_OWNER_COUNT 4
20#define STATUS_SAVED_TILE_BYTES 0x2000
22#define STATUS_SAVED_TILE_BYTES 0x800
27#define STATUS_HELP_TEXT_MAX 0x80
29#define STATUS_HELP_TEXT_MAX 0x40
34#define STATUS_STAT_DIGITS 3
35#define STATUS_STAT_X 200
37#define STATUS_STAT_DIGITS 4
38#define STATUS_STAT_X 192
43#define STATUS_EQUIP_PAGE_SIZE 5
45#define STATUS_EQUIP_PAGE_SIZE 6
50#define STATUS_PSYNERGY_CURSOR_X 55
51#define STATUS_PSYNERGY_CURSOR_Y 60
53#define STATUS_PSYNERGY_CURSOR_X 58
54#define STATUS_PSYNERGY_CURSOR_Y 52
59#define STATUS_EQUIP_SLOT_X 1
60#define STATUS_EQUIP_SLOT_WIDTH 12
62#define STATUS_EQUIP_SLOT_X 2
63#define STATUS_EQUIP_SLOT_WIDTH 9
69#define SHOP_PAGE_ICONS_X 119
70#define SHOP_ITEM_NAME_X 128
73#define SHOP_PAGE_ICONS_X 123
74#define SHOP_ITEM_NAME_X 136
78#if LANGUAGE == LANGUAGE_GERMAN
79#define SHOP_EMPTY_MESSAGE_X 112
81#define SHOP_EMPTY_MESSAGE_X 120
86#define STATUS_EQUIP_WINDOW_WIDTH 15
87#define STATUS_EQUIPPED_NAME_X 8
89#define STATUS_EQUIP_WINDOW_WIDTH 13
90#define STATUS_EQUIPPED_NAME_X 16
110 state->
ownerY[index] = 30;
182 state->
ownerY[index] = 30;
185 for (index = 0; index < 4; index++) {
186 state->
rowX[index] = 130 + index * 32;
187 state->
rowY[index] = 128;
247 step = result == -1 ? 0 : 2;
261 step = (-changed | changed) >> 31;
328 for (i = 0; i < 4; i++) {
329 menu->
slotX[i] = 32 + i * 56;
337 for (element = 0; element < 4; element++) {
338 for (djinn = 0; djinn < 7; djinn++) {
339 s32 id = element * 20 + djinn;
346 element * 56 + 16, djinn * 8 + 24);
363 for (i = 0; i < 4; i++) {
364 menu->
slotX[i] = 130 + i * 32;
365 menu->
slotY[i] = 128;
381static __inline__
void
387 menu->
ownerY[rowIndex] = 30;
411 for (rowIndex = 0; rowIndex < 4; rowIndex++) {
412 menu->
rowX[rowIndex] = 130 + rowIndex * 32;
413 menu->
rowY[rowIndex] = 128;
528 page = (page + 3) % 3;
585 if (direction == 1) {
590 if (selectedIndex == 0) {
603 reordered[clearIndex] = zero;
605 }
while (clearIndex >= 0);
607 u32 *clear = &reordered[13];
612 }
while ((
s32)clear >= (
s32)reordered);
615 for (index = 0; index < menu->
partyCount; index++) {
616 reordered[index] = menu->
ownerIds[index];
619 if (direction == 1) {
620 index = reordered[selectedIndex];
621 reordered[selectedIndex] = reordered[selectedIndex + 1];
622 reordered[selectedIndex + 1] = index;
624 index = reordered[selectedIndex];
625 reordered[selectedIndex] = reordered[selectedIndex - 1];
626 reordered[selectedIndex - 1] = index;
630 for (index = 0; index < menu->
partyCount; index++) {
633 for (index = 0; index < menu->
partyCount; index++) {
720 for (i = 3; i >= 0; i--)
744 pane = (pane + 2) % 2;
746 selected = (selected + limit) % limit;
748 if (hasAilments == 0) {
757 selected = (selected + 8) % 8;
759 selected = (selected + 7) % 7;
774 else if (selected <= 3)
834 for (i = 3; i >= 0; i--)
856 y = selected * 2 + 5;
863 if (selected == count) {
871 }
else if (selected <= 3) {
882 different = 1 ^ invert;
883 palette = 15 - (((0u - different) | different) >> 31);
896 if (
entries[labelIndex] != 0) {
897 if (selected == labelCount) {
898 s32 messageId = MsgStatusAdvice + labelIndex * 2;
905 }
while (labelIndex <= 4);
924 s32 preserveVariant) {
928 if (preserveVariant == 0 && messageVariant > 3) {
931 if (messageVariant == 1) {
934 if (owner->
level == 99) {
971 if ((mode & 0xff) == 1)
979 keepDrawn = mode & 0x100;
990 ailmentIndex * 16 + 40);
995 ailmentIndex * 16 + 40);
1000 ailmentIndex * 16 + 40);
1005 ailmentIndex * 16 + 40);
1008 if (ailmentIndex == 0)
1012 if (menu->
page == 3)
1014 if (keepDrawn == 0) {
1021 if (mode == 1 || hasDjinn == 1) {
1039 for (ailmentIndex = 0; ailmentIndex <= 3; ailmentIndex++) {
1042 window, ailmentIndex * 32 + 120,
1044 if ((mode & 0xff) == 1) {
1047 window, ailmentIndex * 32 + 104,
1050 ailmentIndex * 32 + 112, djinnRow * 8 + 8);
1054 ailmentIndex * 32 + 112, djinnRow * 8 + 16);
1056 ailmentIndex * 32 + 104, djinnRow * 8 + 24);
1058 window, ailmentIndex * 32 + 104,
1137 for (ailmentIndex = 4; ailmentIndex >= 0; ailmentIndex--)
1138 ailments[ailmentIndex] = 0;
1141 if (unit->
hp == 0 && requested == 1) {
1158 if (unit->
haunt != 0) {
1194 result->
page = page;
1218 for (set = 0; set < 2; set++) {
1219 for (tileIndex = 0; tileIndex < 6; tileIndex++) {
1220 u32 *tile = vram + set * 0x60 + tileIndex * 0x10;
1224 for (rowIndex = 1; rowIndex <= 7; rowIndex++) {
1225 s32 mask = tileIndex;
1227 if (set == 1 && rowIndex <= 1) {
1230 if (set == 0 && tileIndex > rowIndex - 2) {
1231 mask = rowIndex - 2;
1238 tile[rowIndex + 8] =
1254 iconIndex = range * 2;
1273#if TBS_PATCH_1 && !TBS_PATCH_4
1284 MsgAbilityDescription,
1288#if LANGUAGE != LANGUAGE_JAPANESE
1291 if (ability->
type0c != 0 ||
1300 }
else if (row == 2) {
1302 }
else if (row == 1) {
1308 if (ability->
type0c != 0 ||
1323 for (row = 0; row <=
PAGE_ROWS - 1; row++) {
1324 if (row == state->
row) {
1386 entryIndex = firstEntry;
1403 if (
range == 0xff) {
1412 }
while (rows > row);
1422#if LANGUAGE == LANGUAGE_SPANISH || LANGUAGE == LANGUAGE_FRENCH
1438 s32 listNeedsRedraw;
1439 s32 navigationResult;
1450 for (iconIndex = 3; iconIndex >= 0; iconIndex--)
1451 menu->
slotY[iconIndex] = -16;
1456 for (iconIndex = 31; iconIndex >= 0; iconIndex--) {
1480 listNeedsRedraw = 1;
1485 if (listNeedsRedraw != 0) {
1486 listNeedsRedraw = 0;
1498 if (navigationResult == 1) {
1499 listNeedsRedraw = 1;
1502 if (navigationResult == 0)
1504 if (navigationResult == -1)
1574#if TBS_PATCH_1 && !TBS_PATCH_4
1588 for (rowIndex = 0; rowIndex <
PAGE_ROWS; rowIndex++) {
1589 if (rowIndex == state->
row) {
1594 rowIndex * 2 + 1, 0);
1604 rowIndex * 2 + 1, 4);
1612 for (rowIndex = 0; rowIndex <= 3; rowIndex++) {
1619 switch (item->
type) {
1646 u16 *inventoryEntry;
1665 if (rowCount > rowIndex) {
1666 inventoryEntry = &menu->
items[firstEntry];
1669 (*inventoryEntry &
ITEM_ID_MASK) + MsgItemName, window,
1671 rowIndex = (
u8)(rowIndex + 1);
1673 }
while (rowCount > rowIndex);
1677 message = MsgStatLabel;
1692 s32 listNeedsRedraw;
1693 s32 navigationResult;
1696 u16 savedInventory[15];
1710 for (iconIndex = 0; iconIndex < 32; iconIndex++) {
1731 for (iconIndex = 0; iconIndex <= 14; iconIndex++)
1732 savedInventory[iconIndex] = owner->
inventory[iconIndex];
1741 listNeedsRedraw = 1;
1747 if (listNeedsRedraw != 0) {
1748 listNeedsRedraw = 0;
1759 if (navigationResult == 1) {
1760 listNeedsRedraw = 1;
1763 if (navigationResult == 0)
1765 if (navigationResult == -1)
1789 for (iconIndex = 0; iconIndex <= 14; iconIndex++)
1790 owner->
inventory[iconIndex] = savedInventory[iconIndex];
1815 column = *columnOut;
1817 switch (direction) {
1830 }
else if (column > 1) {
1833 if ((row == 3) && (column == 1)) {
1843 if ((row == 3) && (column == 1)) {
1854 }
else if (row > 3) {
1858 }
else if (column < 0) {
1866 }
else if (row > 3) {
1870 }
else if (column > 1) {
1875 *columnOut = column;
1877 return (row * 9) + column;
1908 for (slotIndex = 0; slotIndex < 15; slotIndex++) {
1947 }
while (entryIndex <= 0x1F);
1952 s32 originX,
s32 originY,
s32 columns) {
1956 if (entryIndex > 0x1F) {
1959 icon->
y = (entryIndex / columns * 0x10) + originY;
1960 icon->
x = (entryIndex % columns * 0x10) + originX;
1972 for (slotIndex = 0; slotIndex < 15; slotIndex++) {
2017 }
while (remaining >= 0);
2038 }
while (slotIndex <= 7);
2060 if (entry != 0 && flags[
index] != 0) {
2072 }
while (
index <= 4);
2080 for (index = 0; index < 5; index++) {
2086 object->sentinel = 240;
2098 if (enabled[index] != 0) {
2124 }
while (index <= 4);
2128#undef CHARACTER_SELECTOR_OWNER_COUNT
2129#undef STATUS_SAVED_TILE_BYTES
2130#undef STATUS_HELP_TEXT_MAX
2131#undef STATUS_STAT_DIGITS
2133#undef STATUS_EQUIP_PAGE_SIZE
2134#undef STATUS_PSYNERGY_CURSOR_X
2135#undef STATUS_PSYNERGY_CURSOR_Y
2136#undef STATUS_EQUIP_SLOT_X
2137#undef STATUS_EQUIP_SLOT_WIDTH
2138#undef SHOP_PAGE_ICONS_X
2139#undef SHOP_ITEM_NAME_X
2141#undef SHOP_EMPTY_MESSAGE_X
2142#undef STATUS_EQUIP_WINDOW_WIDTH
2143#undef STATUS_EQUIPPED_NAME_X
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,...
void Menu_ReleaseEntryObjects(void)
Releases the party figures PsynergyMenu_InitializeEntryObjects created and stops their placement call...
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.
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...
void UiIcon_PrepareObject(struct RenderOutput *object)
Shows a menu icon at its stored position, without rotation or scaling.
void Palette_LightenBankHighlight(s32 bank)
Copies the last background palette (15) into background palette bank and lightens its colour 4 by 9 s...
void PsynergyMenu_CallIconRoutineWithValue(const void *unused, s32 unit)
Loads the graphics of character unit into menu entry slot 0.
void Menu_UpdateEntryObjectTransforms(void)
Scheduler callback: each frame, places every party member sprite created by PsynergyMenu_InitializeEn...
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...
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...
void UiMenu_PositionCursor(s32 xOffset, s32 yOffset)
Places the hand cursor at (xOffset, yOffset) inside the menu's top-left window, bobbing.
void Menu_CancelSoundReset(void)
Starts watching for Start: clears FLAG_MENU_START_PRESSED and adds Menu_CancelSoundTick.
s32 Menu_SuspendFieldTasks(void)
Suspends the overlay tasks and tile animations while a menu is open, and sets flags 0x152 and 0x166.
void UiWindow_InitializeWork(s32 unused)
Clears the whole menu work and sets its defaults: no pane selected, one entry in each pane,...
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 (...
void Menu_EnsureCancelSound(void)
Stops watching for Start, if Start has not removed the watch already.
s32 Menu_ResumeFieldTasks(void)
Resumes the overlay tasks and tile animations when a menu closes, and clears game flags 0x166 and 0x1...
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.
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,...
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.
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...
s32 Party_AddActiveOwnerFar(s32 value)
struct BattleUnit * UnitGetFar(u32 owner)
struct ItemDefinition * Item_GetDirectFar(s32 item)
s32 Party_ListActiveOwnersFar(s16 *owners)
s32 GameFlag_TestFar(s32 flag)
struct BattleAct * BattleActGet(s32 actionId)
Far call to BattleAction_GetDirect.
s32 Unit_GetElementLevelFar(s32 owner, s32 index)
s32 Party_RemoveActiveOwnerFar(s32 value)
s32 Party_SumDjinnCountsFar(s32 index)
u32 Unit_GetExperienceForLevelFar(s32 owner, s32 level)
void AudioCommand_PlayFar(s32 id)
struct UiWindow * UiWindow_CreateFar(s32 x, s32 y, s32 width, s32 height, s32 attrs)
void UiWindow_DrawFrameFar(s32 x, s32 y, u32 width, u32 height)
void UiWindow_MarkVisibleTileAttributesFar(void)
void RenderOutput_ClearListFar(void *work)
void UiWindow_EraseBorderRectFar(s32 x, s32 y, u32 width, u32 height)
void UiText_DrawNumberInWindowFar(s32 arg0, s32 arg1, struct UiWindow *arg2, s32 arg3, s32 arg4)
void UiWork_SetParamNibbleFar(s32 param)
s32 Resource_LoadByModeIntoSlotFar(s32 mode, s32 value, s32 result, s32 option)
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.
s32 UiText_CopyMessageStringFar(s32 key, u16 *destination, u32 capacity)
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)
void UiText_RenderWideStringAtOffsetFar(u16 *text, struct UiWindow *window, s32 x, s32 y)
void UiText_DrawResourceFar(s32 arg0, struct UiWindow *arg1, s32 arg2, s32 arg3)
void UiText_DrawStringAtOffsetFar(const u8 *text, const struct UiWindow *work, s32 offsetX, s32 offsetY)
struct RenderOutput * RenderOutput_CreateFromResourceFar(s32 mode, s32 resource, struct UiWindow *input, s32 x, s32 y)
void UiWork_PushValueSlotFar(u32 value, u32 kind)
void UiWork_SetAltFlagAndClearTableFar(s32 flag)
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)
#define FLAG_DJINNI_0
the flag of Djinni 0, set once it is caught
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
void * Runtime_BumpAllocateAlternatePool(s32 size)
As MemAlloc, but tries EWRAM first.
void * MemAlloc(s32 size)
Allocates size bytes (rounded up to words) with no slot, from IWRAM when they fit and EWRAM otherwise...
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
#define BG_PLTT_COLOR(palette, color)
void ItemMenu_Close(void)
Closes the item menu: releases the party figures, hides the icons and the cursor, and closes every wi...
void Menu_SpawnIconEntries(struct InventoryMenuState *state, struct UiWindow *window)
Creates the 32 item icon sprites in window, off screen until placed: slots 0 to 7 at x 248,...
void ItemMenu_DrawIcons(u16 *inventoryEntries, s32 iconStyle)
Loads each listed item's icon into its item icon sprite, the first 15 entries of inventoryEntries,...
void Menu_HideEmptyEntryIcons(const u16 *items)
Hides the icon of each of the 32 list entries whose item is 0.
void ItemMenu_HideAllIcons(void)
Hides all 32 item icons.
s32 ItemMenu_CollectItems(struct BattleUnit *unit, u16 *items, s32 mode)
Copies the unit's items into the list items (32 entries), skipping empty slots and clearing the rest.
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
static s32 Iwram_FillWords(void *destination, s32 size, u32 value)
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)
void MemFree(void *buffer)
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...
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
#define SE_MENU_CURSOR_MOVE
An ability's definition, a row of gBattleAction_DefinitionTable: its targeting, kind,...
u8 type0c
The field Psynergy the ability works as, 1 (Move) to 16 (Avoid); 0 for none.
u8 ppCost
PP the ability costs.
u8 range
the aimed unit and range - 1 either side, or ABILITY_RANGE_ALL
u8 flags
bits: 7 usable in battle | 6 usable in the field | 5..4 clear in every row | 3..0 kind (ABILITY_KIND_...
s16 resistance
Elemental resistance to it.
s16 power
Elemental power in the element.
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 luck
0 to 99 (UnitCalc)
u8 djinnOwnedCounts[4]
the Djinn held in each element, at most 10
s16 maxPp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
s8 poison
1 poisoned, 2 deadly poison
u8 djinnActiveCounts[4]
the Djinn set in each element; the class's element levels are read from these
u8 name[0x0f]
The name, one byte a character, ending in 0.
u8 haunt
set while an evil spirit grips the unit
s16 hp
current HP, 0 when downed
struct BattleElementStats element[4]
Power and resistance in each element, 0 to 200, after equipment, element levels and Resistance stages...
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_*...
An item's definition: its price, type, who can equip it, its bonuses and unleash, its effects and the...
u8 type
enum ItemType; 0 for an item that is not equipment
s32 element
a weapon's attack element; 4 for none
The object system's work: the flag that suspends sprite projection, the outline's edge and fill colou...
s16 suspended
nonzero while a menu has suspended sprite projection
A render output: a sprite in a window's output list (a character, an icon or a portrait),...
u8 sentinel
depth slot it is drawn at (254 for glyphs)
s8 active
its UI_SPRITE_ motion; 0 while free
u16 animStep
step of its motion's animation
s8 index
VRAM cache slot, or a glyph's tile after glyphTiles.
One row's masks for a pair of bar-pattern tiles: a word XORed into each tile's row.
The window system's work: the windows' tilemap, the windows, the three text channels,...
u8 menuBusy
while set, the tilemap is not uploaded
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
A view of the window system's work that names only its dirty bits and its menu busy flag.
#define UI_PAGE_ARROW_VRAM