14#define DJINN_CURSOR_WIDTH 6
16#define DJINN_CURSOR_WIDTH 5
20#define DJINN_SWAP_PREVIEW_MODE 2
22#define DJINN_SWAP_PREVIEW_MODE 4
28#define DJINN_PREVIEW_DIGITS 3
29#define DJINN_PREVIEW_CURRENT_X 48
30#define DJINN_PREVIEW_MAX_X 80
31#define DJINN_PREVIEW_SLASH_X 72
32#define DJINN_PREVIEW_LUCK_X 56
33#define DJINN_PREVIEW_ARROW_X(x, iconX) (iconX)
34#define DJINN_PREVIEW_PP_X 88
36#define DJINN_PREVIEW_DIGITS 4
37#define DJINN_PREVIEW_CURRENT_X 32
38#define DJINN_PREVIEW_MAX_X 72
39#define DJINN_PREVIEW_SLASH_X 64
40#define DJINN_PREVIEW_LUCK_X 48
41#define DJINN_PREVIEW_ARROW_X(x, iconX) ((x) * 8 + 64)
42#define DJINN_PREVIEW_PP_X 56
48 return (value + modulus) % modulus;
59 for (ownerIndex = 0; ownerIndex < 4; ownerIndex++) {
61 menu->
ownerY[ownerIndex] = yOffset;
70 u32 savedMessageSpeed;
140#define DJINN_RESELECT_PAIR_ENTRY(menu, i) \
146 column = (u16)((u32)(menu)->selection[1] % DJINN_LIST_ROWS); \
148 entry = (menu)->pairEntries[0]; \
149 for ((i) = 0; (i) < (menu)->backdrop->list.counts[column]; (i)++) { \
150 if (entry == (u8)(menu)->backdrop->list.ids[column][(i)]) { \
155 (menu)->selection[0] = column + found * DJINN_LIST_ROWS; \
261 for (listIndex = 0; listIndex < menu->
ownerCount; listIndex++)
262 menu->
ownerY[listIndex] += 8;
269 if (result == 3 || result == 4 || result == 8 || result == 9)
273 else if (result == 1)
275 else if (result == 2)
277 else if (result == 3) {
280 }
else if (result == 4) {
283 }
else if (result == 5)
285 else if (result == 6)
287 else if (result == 8) {
290 }
else if (result == 9) {
412 for (colorIndex = 0; colorIndex <= 15; colorIndex++) {
419 paletteIndex = bank * 16 + colorIndex;
421 blue = (color >> 10) & mask;
422 green = (color >> 5) & mask;
424 blue += brightnessDelta;
425 green += brightnessDelta;
426 red += brightnessDelta;
439 adjustedColor = blue << 10;
440 adjustedColor |= green << 5;
441 adjustedColor |= red;
443 ((
s16 *)
BG_PLTT - 16)[paletteIndex] = adjustedColor;
445 if (bankIndex == 0) {
449 brightnessDelta = -12;
452 }
while (bankIndex <= 2);
455#define DJINN_BACKDROP_FRAME_TILE 150
457#define DJINN_PREVIEW_GAINED 0x8000
458#define DJINN_PREVIEW_LOST 0x4000
497 s32 *gainedCountOut,
s32 *lostCountOut) {
507 for (actionIndex = 0;
510 actionsOut[actionCount] =
513 for (otherIndex = 0; otherIndex < 32; otherIndex++) {
514 if (((after[actionIndex].encodedAction ^
515 before[otherIndex].encodedAction) &
519 if (otherIndex == 32) {
524 for (actionIndex = 0;
527 for (otherIndex = 0; otherIndex < 32; otherIndex++) {
528 if (((before[actionIndex].encodedAction ^
529 after[otherIndex].encodedAction) &
533 if (otherIndex == 32) {
535 actionsOut[actionCount] =
541 *gainedCountOut = gainedCount;
542 *lostCountOut = lostCount;
571 }
while (ownerIndex < ownerCount);
580#define DJINN_ELEMENT_TILE 0x5001
600 table->
ids[listIndex], menu->
owners[listIndex], -1);
602 }
while (listIndex < menu->ownerCount);
606 for (row = 0; row < menu->
ownerCount; row++) {
607 entries = table->
ids[row];
610 for (listIndex = 0; listIndex < table->
counts[row]; listIndex++) {
629 row * 7 + 1, lineIndex + 2, 0);
635 menu->
listWindow, row * 56 + 16, lineIndex * 8 + 16);
682 if (width > 0 && height > 0) {
685 for (column = width; column != 0; column--) {
687 if (((tile >> 12) & 15) == 15) {
688 masked = tile & 0xffff0fff;
696 }
while (height != 0);
703 s32 height,
s32 palette) {
705 ((
struct UiWindow *)window)->y + y + 1, width, height,
732 message = MsgDjinnInfoPrompt;
743 listMessage = MsgDjinnInfoTopic;
748 }
while (helpIndex <= 6);
753 helpWindow, selection + MsgDjinnInfoText);
756 previous = selection;
803 }
while (result == 0);
822#define DJINN_ENTRY_SET (-0x8000)
824#define DJINN_OWNER(v) (((v) & 0xf00) >> 8)
825#define DJINN_ELEMENT(v) (((v) & 0xe0) >> 5)
826#define DJINN_NUMBER(v) ((v) & 0x1f)
832 u8 requiresTrade[16];
858 status = columnFlags;
859 for (i = 7; i >= 0; i--)
869 if (status[ownerColumn] == 4) {
879 }
else if (requiresTrade[i] != 0) {
884 status[i] = columnFlags[i] | 4;
894 fromX = (
u16)((
u32)sourceCursor % (
u32)10);
895 fromY = (
u16)((
u32)sourceCursor / (
u32)10);
903 message = MsgDjinnStandbyAction;
905 message = MsgDjinnSetAction;
906 }
else if (columnFlags[n] & 2) {
907 message = MsgDjinnGiveAction;
909 message = MsgDjinnTradeAction;
921 if (!(columnFlags[ownerColumn] & 1))
922 selectedRow = djinnRow;
933 if (selectedRow != -1)
934 djinn = backdrop->
list.
ids[ownerColumn][selectedRow];
937#if LANGUAGE == LANGUAGE_SPANISH || LANGUAGE == LANGUAGE_FRENCH || \
938 LANGUAGE == LANGUAGE_ITALIAN
964 if (selectedRow == -1) {
966 }
else if (mode == 0) {
1043 if (selectedRow != -1) {
1057 if (!(columnFlags[ownerColumn] & 1))
1059 ownerColumn * 7 + 1, djinnRow + 2,
1063 if (columnFlags[ownerColumn] & 1)
1077 if (tutorialStep != 0) {
1081 switch (tutorialStep) {
1155 MsgDjinnTutorialSetAfterGive, 9, 9, 1);
1249 if (mode == 0 && (pressed &
KEY_R)) {
1250 if (selectedRow == -1) {
1287 if (mode == 0 && (pressed &
KEY_L)) {
1292 if ((pressed &
KEY_A) || (mode == 1 && (pressed &
KEY_R))) {
1294 if (!(columnFlags[ownerColumn] & 1)) {
1295 if (selectedRow == -1) {
1314 if (columnFlags[ownerColumn] & 1) {
1337 if (pressed &
KEY_B) {
1350 for (j = 0; j < backdrop->
list.
counts[i]; j++) {
1385 ownerColumn * 7 + 1, djinnRow + 2,
1393 if (columnFlags[ownerColumn] & 4)
1398 if (columnFlags[ownerColumn] & 4)
1400 if (columnFlags[ownerColumn] & 1) {
1401 columnFlags[ownerColumn] &= ~1;
1403 }
else if (djinnRow == 0 && (columnFlags[ownerColumn] & 2)) {
1404 columnFlags[ownerColumn] |= 1;
1413 savedRow = djinnRow;
1419 if (columnFlags[ownerColumn] & 4)
1429 if ((columnFlags[ownerColumn] & 1) && !(columnFlags[ownerColumn] & 4)) {
1430 columnFlags[ownerColumn] &= ~1;
1432 }
else if (djinnRow == 0 && (columnFlags[ownerColumn] & 2)) {
1433 columnFlags[ownerColumn] |= 1;
1435 savedRow = djinnRow;
1441 if (!(columnFlags[ownerColumn] & 4))
1443 ownerColumn * 7 + 1, djinnRow + 2,
1449 if (columnFlags[ownerColumn] == 4) {
1455 djinnRow = savedRow;
1465 if (!(columnFlags[ownerColumn] & 4))
1467 ownerColumn * 7 + 1, djinnRow + 2,
1473 if (columnFlags[ownerColumn] == 4) {
1479 djinnRow = savedRow;
1488 if (selectedRow != -1) {
1491 backdrop->
list.
ids[ownerColumn][selectedRow];
1498 asm(
"" :
"+r"(result) :
"r"(entry));
1500 menu->
selection[mode] = ownerColumn + djinnRow * 10;
1514 for (elementIndex = 0; elementIndex < 4; elementIndex++) {
1515 for (djinnIndex = 0; djinnIndex < 20; djinnIndex++) {
1516 if (unit->
djinnActive[elementIndex] & (1 << djinnIndex)) {
1518 encodedDjinn |= ownerId << 8;
1519 entriesOut[count++] = encodedDjinn;
1520 }
else if (unit->
djinnAvailable[elementIndex] & (1 << djinnIndex)) {
1521 entriesOut[count++] =
1522 (elementIndex << 5) | djinnIndex | (ownerId << 8);
1527 for (djinnIndex = 0; djinnIndex < 20; djinnIndex++) {
1531 entriesOut[count++] = (
element << 5) | djinnIndex;
1544 mode, 2, pageIndex, 1);
1546 2, pageIndex, mode);
1565 s32 ownerId,
s32 removePairSlot,
s32 addPairSlot,
1583 giveIndex = menu->
pairIndex[removePairSlot];
1584 giveSet = menu->
pairEntries[removePairSlot] & 0x8000;
1586 takeIndex = menu->
pairIndex[addPairSlot];
1587 takeSet = menu->
pairEntries[addPairSlot] & 0x8000;
1592 if (previewMode == 3) {
1622 switch (previewMode) {
1658 label = MsgPreviewStatLabel;
1666 window, x * 8, y * 8 + 32);
1688 for (i = 0; i < 4; i++) {
1690 column + i * 2, y + 5, 0);
1692 column + i * 2 + 1, y + 5, 0);
1697 if (unit->
hp != originalUnit->
hp) {
1700 if (unit->
hp > originalUnit->
hp)
1707 if (unit->
pp != originalUnit->
pp) {
1710 if (unit->
pp > originalUnit->
pp)
1717 if (unit->
atk != originalUnit->
atk) {
1720 if (unit->
atk > originalUnit->
atk)
1727 if (unit->
def != originalUnit->
def) {
1730 if (unit->
def > originalUnit->
def)
1737 if (unit->
agi != originalUnit->
agi) {
1740 if (unit->
agi > originalUnit->
agi)
1747 if (unit->
luck != originalUnit->
luck) {
1750 if (unit->
luck > originalUnit->
luck)
1767 rows = 6 - (previewMode != 3);
1768 first = rows * (page - 1);
1770 actions, &gained, &lost);
1772 for (row = 0; first < count && row < rows; row++, first++) {
1775 if (actions[first] & 0x8000)
1777 else if (actions[first] & 0x4000)
1783 x * 8 + 16, (y + line * 2) * 8 + 8);
1785 window, x * 8 + 88, (y + line * 2) * 8 + 8);
1791 if (previewMode != 3) {
1804 (y + lines) * 8 + 88);
1824#undef DJINN_CURSOR_WIDTH
1825#undef DJINN_SWAP_PREVIEW_MODE
1826#undef DJINN_PREVIEW_DIGITS
1827#undef DJINN_PREVIEW_CURRENT_X
1828#undef DJINN_PREVIEW_MAX_X
1829#undef DJINN_PREVIEW_SLASH_X
1830#undef DJINN_PREVIEW_LUCK_X
1831#undef DJINN_PREVIEW_ARROW_X
1832#undef DJINN_PREVIEW_PP_X
1833#undef DJINN_RESELECT_PAIR_ENTRY
1834#undef DJINN_BACKDROP_FRAME_TILE
1835#undef DJINN_PREVIEW_GAINED
1836#undef DJINN_PREVIEW_LOST
1837#undef DJINN_ELEMENT_TILE
1838#undef DJINN_ENTRY_SET
#define DJINN_PER_ELEMENT
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 Palette_LightenBankHighlight(s32 bank)
Copies the last background palette (15) into background palette bank and lightens its colour 4 by 9 s...
void Menu_UpdateEntryObjectTransforms(void)
Scheduler callback: each frame, places every party member sprite created by PsynergyMenu_InitializeEn...
void UiMenu_PositionCursor(s32 xOffset, s32 yOffset)
Places the hand cursor at (xOffset, yOffset) inside the menu's top-left window, bobbing.
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,...
s32 Menu_ResumeFieldTasks(void)
Resumes the overlay tasks and tile animations when a menu closes, and clears game flags 0x166 and 0x1...
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 DjinnRecovery_TickFar(void)
struct BattleUnit * UnitGetFar(u32 owner)
s32 Party_ListActiveOwnersFar(s16 *owners)
s32 GameFlag_TestFar(s32 flag)
u32 * DjinnRecovery_AddStandbyFar(u32 kind, u32 first, u32 second)
struct BattleAct * BattleActGet(s32 actionId)
Far call to BattleAction_GetDirect.
u32 Djinn_IsActiveFar(s32 owner, s32 index, s32 bit)
s32 Djinn_TransferFar(s32 source, s32 index, s32 bit, s32 target)
s32 DjinnRecovery_RemoveFar(s32 owner, s32 index, s32 bit)
u32 Djinn_DeactivateFar(s32 owner, s32 index, s32 bit)
s32 Djinn_AddToOwnerFar(s32 owner, s32 index, s32 bit)
s32 Djinn_IsReadyFar(s32 owner, s32 index, s32 bit)
s32 Djinn_ActivateFar(s32 owner, s32 index, s32 bit)
void UnitCalcFar(s32 owner)
void Event_ClearInvalidPackedValuesFar(void)
void AudioCommand_PlayFar(s32 id)
void RenderOutput_PrepareForRedrawFar(struct UiWindow *window)
struct UiWindow * UiWindow_CreateFar(s32 x, s32 y, s32 width, s32 height, s32 attrs)
void UiWindow_SetPaletteBitRectFar(s32 x, s32 y, s32 width, s32 height, s32 alt)
Far call to Ui_SetRectHighlight.
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)
s32 UiText_OpenEntryMessageFar(struct UiWindow *window, s32 argument)
void UiWork_SetParamNibbleFar(s32 param)
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)
void Graphics_ExpandVramTilesByColorTableFar(u16 *dst)
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 UiWork_PushValueSlotFar(u32 value, u32 kind)
s32 UiWork_IsCompleteFar(void)
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)
struct UiWindow * UiText_OpenMessageWindowFar(s32 message, s32 x, s32 y, u32 packed)
#define FLAG_DJINN_TUTORIAL
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
struct GameState gGameState
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 ItemMenu_Initialize(s32 x, s32 y, s32 mode, s32 columns)
Sets up the item menu's first screen: the cursor window with the party's figures, the info window alo...
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 gKeysHeld
Keys down now.
volatile u32 gKeysPressed
Keys that went down this frame.
u32 gKeysPressedLatch
Presses since a reader last cleared it.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
s32 Palette_GetBasicObjColors(void)
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...
#define SE_MENU_CURSOR_MOVE
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 luck
0 to 99 (UnitCalc)
u32 djinnActive[4]
The Djinn set, one bit per Djinni; only these add their stat bonuses.
s16 maxPp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
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.
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...
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)
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).
u32 djinnAvailable[4]
The Djinn held, one bit per Djinni (by its index) in each element's word.
The Djinn menu's lists: each party member's Djinn entries and their count.
u16 ids[DJINN_LIST_OWNERS][DJINN_LIST_ROWS]
s8 counts[DJINN_LIST_OWNERS]
u8 messageSpeed
0 to 2; 1 on a new game
s16 suspended
nonzero while a menu has suspended sprite projection
An entry in a unit's action list: the action's id (OWNER_ACTION_ID_MASK) and marks for an action its ...
u16 encodedAction
bits: 15 from the class | 14 from an equipped item | 13..0 action id.
A render output: a sprite in a window's output list (a character, an icon or a portrait),...
s8 active
its UI_SPRITE_ motion; 0 while free
u16 animStep
step of its motion's animation
A text channel, one of three, which types decoded text into a window a few characters a frame and run...
struct UiWindow * work
the window typed into; NULL when free
The window system's work: the windows' tilemap, the windows, the three text channels,...
u8 mode
Set while Mind Read shows thoughts: round frame corners, colour 8 text with no shadow,...
u16 tilemap[640]
the windows' BG tilemap, 32 by 20 tiles
u16 tileCursor
the text tile the next search for a free one starts at
u16 glyphResource
VRAM cache slot of the page arrow; 99 when none.
u8 pageArrowShown
1 while the next-page arrow is shown
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...
u16 frame
The zoom's step: counts down from 7 to 0 while opening, and up from 0 to duration while closing.
u16 state
0 while a message channel is typing into the window; 1 once its text has ended or closed the window,...
s16 duration
frames of the zoom under way; 0 when none
A view of the window system's work that names only its dirty bits and its menu busy flag.
#define UiRender_MarkRow(render, y)
Requests transfer of the four-row tilemap band containing window row y.
#define UI_PAGE_ARROW_VRAM
s32 Resource_ResetEntry(u32 no)
Frees cache entry no: its blocks go back and the entry is marked free (offset 0xffff).