summaryrefslogtreecommitdiff
path: root/src/union_room_chat_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/union_room_chat_display.c')
-rw-r--r--src/union_room_chat_display.c1339
1 files changed, 1339 insertions, 0 deletions
diff --git a/src/union_room_chat_display.c b/src/union_room_chat_display.c
new file mode 100644
index 000000000..54aef8d65
--- /dev/null
+++ b/src/union_room_chat_display.c
@@ -0,0 +1,1339 @@
+#include "global.h"
+#include "gflib.h"
+#include "dynamic_placeholder_text_util.h"
+#include "graphics.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "scanline_effect.h"
+#include "strings.h"
+#include "text_window.h"
+#include "union_room_chat.h"
+#include "union_room_chat_display.h"
+#include "union_room_chat_objects.h"
+
+#define STDMESSAGE_QUIT_CHATTING 0
+#define STDMESSAGE_REGISTER_WHERE 1
+#define STDMESSAGE_REGISTER_HERE 2
+#define STDMESSAGE_INPUT_TEXT 3
+#define STDMESSAGE_EXITING_CHAT 4
+#define STDMESSAGE_LEADER_LEFT 5
+#define STDMESSAGE_ASK_SAVE 6
+#define STDMESSAGE_ASK_OVERWRITE 7
+#define STDMESSAGE_SAVING_NO_OFF 8
+#define STDMESSAGE_SAVED_THE_GAME 9
+#define STDMESSAGE_WARN_LEADER_LEAVE 10
+
+struct UnionRoomChat2Subtask
+{
+ bool32 (*callback)(u8 *);
+ u8 active;
+ u8 state;
+};
+
+struct UnionRoomChat2
+{
+ struct UnionRoomChat2Subtask subtasks[3];
+ u16 yesNoMenuWinId;
+ u16 curLine;
+ u16 scrollCount;
+ u16 messageWindowId;
+ s16 bg1hofs;
+ u8 expandedPlaceholdersBuffer[0x106];
+ u8 bg0Buffer[BG_SCREEN_SIZE];
+ u8 bg1Buffer[BG_SCREEN_SIZE];
+ u8 bg3Buffer[BG_SCREEN_SIZE];
+ u8 bg2Buffer[BG_SCREEN_SIZE];
+ u8 unk2128[0x20];
+ u8 unk2148[0x20];
+};
+
+struct SubtaskInfo
+{
+ u16 idx;
+ bool32 (*callback)(u8 *);
+};
+
+struct MessageWindowInfo
+{
+ const u8 *text;
+ bool8 boxType;
+ u8 x;
+ u8 y;
+ u8 letterSpacing;
+ u8 lineSpacing;
+ bool8 expandPlaceholders;
+ bool8 widerBox;
+};
+
+static EWRAM_DATA struct UnionRoomChat2 * sWork = NULL;
+
+static void InitWork(struct UnionRoomChat2 * ptr);
+static void UnionRoomChat_ResetDisplaySubtasks(void);
+static bool32 DisplaySubtask_LoadGfx(u8 *state);
+static bool32 DisplaySubtask_PrintWin3(u8 *state);
+static bool32 DisplaySubtask_HideWin3(u8 *state);
+static bool32 DisplaySubtask_SwitchPages(u8 *state);
+static bool32 DisplaySubtask_MoveSelectorCursorObj(u8 *state);
+static bool32 DisplaySubtask_ShowQuitChattingDialog(u8 *state);
+static bool32 DisplaySubtask_HideQuitChattingDialog(u8 *state);
+static bool32 DisplaySubtask_UpdateMessageBuffer(u8 *state);
+static bool32 DisplaySubtask_PrintRegisterWhere(u8 *state);
+static bool32 DisplaySubtask_CancelRegister(u8 *state);
+static bool32 DisplaySubtask_ReturnToKeyboard(u8 *state);
+static bool32 DisplaySubtask_ScrollChat(u8 *state);
+static bool32 DisplaySubtask_AnimateSelectorCursorBlink(u8 *state);
+static bool32 DisplaySubtask_PrintInputText(u8 *state);
+static bool32 DisplaySubtask_PrintExitingChat(u8 *state);
+static bool32 DisplaySubtask_PrintLeaderLeft(u8 *state);
+static bool32 DisplaySubtask_AskSave(u8 *state);
+static bool32 DisplaySubtask_AskOverwriteSave(u8 *state);
+static bool32 DisplaySubtask_PrintSavingDontTurnOffPower(u8 *state);
+static bool32 DisplaySubtask_PrintSavedTheGame(u8 *state);
+static bool32 DisplaySubtask_ShowConfirmLeaderLeaveDialog(u8 *state);
+static bool32 DisplaySubtaskDummy(u8 *state);
+static void PlaceYesNoMenuAt(u8 a0, u8 a1, u8 a2);
+static void HideYesNoMenuWindow(void);
+static void DestroyYesNoMenuWindow(void);
+static void PlaceStdMessageWindow(int id, u16 bg0vofs);
+static void HideStdMessageWindow(void);
+static void DestroyStdMessageWindow(void);
+static void FillWin1Rect(u16 x, u16 width, u8 fillValue);
+static void PrintOnWin1Parameterized(u16 x, u8 *str, u8 bgColor, u8 fgColor, u8 shadowColor);
+static void PrintCurrentKeyboardPage(void);
+static bool32 AnimateMoveBg1Right(void);
+static bool32 AnimateMoveBg1Left(void);
+static void PrintKeyboardSwapTextsOnWin3(void);
+static void ClearWin3(void);
+static void PrintTextOnWin0Colorized(u16 row, u8 *str, u8 colorIdx);
+static void ResetGpuBgState(void);
+static void SetBgTilemapWorkBuffers(void);
+static void ClearBg0(void);
+static void LoadUnionRoomChatPanelGfx(void);
+static void LoadLinkMiscMenuGfx(void);
+static void LoadBg1Pal8(void);
+static void LoadWin0(void);
+static void LoadWin2(void);
+static void LoadWin1(void);
+static void LoadWin3(void);
+static void sub_812AD50(void);
+static void FillScanlineEffectWithValue1col(s16 a0);
+static void FillScanlineEffectWithValue2col(s16 a0);
+
+static const u16 sUnionRoomChatPanelBgPal_C[] = INCBIN_U16("graphics/union_room_chat/unk_845AA24.gbapal");
+static const u16 sBg1Pal8[] = INCBIN_U16("graphics/union_room_chat/unk_845AA44.gbapal");
+static const u16 sWin0PalF[] = INCBIN_U16("graphics/union_room_chat/unk_845AA64.gbapal");
+
+static const struct BgTemplate gUnknown_845AA84[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 7,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x0000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x0000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 23,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x0000
+ }, {
+ .bg = 3,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 15,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x0001
+ }
+};
+
+static const struct WindowTemplate gUnknown_845AA94[] = {
+ {
+ .bg = 3,
+ .tilemapLeft = 8,
+ .tilemapTop = 1,
+ .width = 21,
+ .height = 19,
+ .paletteNum = 15,
+ .baseBlock = 0x001
+ }, {
+ .bg = 1,
+ .tilemapLeft = 9,
+ .tilemapTop = 18,
+ .width = 15,
+ .height = 2,
+ .paletteNum = 12,
+ .baseBlock = 0x07a
+ }, {
+ .bg = 1,
+ .tilemapLeft = 0,
+ .tilemapTop = 2,
+ .width = 6,
+ .height = 15,
+ .paletteNum = 7,
+ .baseBlock = 0x020
+ }, {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 2,
+ .width = 7,
+ .height = 9,
+ .paletteNum = 14,
+ .baseBlock = 0x013
+ }, DUMMY_WIN_TEMPLATE
+};
+
+static const struct SubtaskInfo sSubtaskInfo[] = {
+ {CHATDISPLAYROUTINE_LOADGFX, DisplaySubtask_LoadGfx},
+ {CHATDISPLAYROUTINE_SHOWKBSWAPMENU, DisplaySubtask_PrintWin3},
+ {CHATDISPLAYROUTINE_HIDEKBSWAPMENU, DisplaySubtask_HideWin3},
+ {CHATDISPLAYROUTINE_SWITCHPAGES, DisplaySubtask_SwitchPages},
+ {CHATDISPLAYROUTINE_MOVEKBCURSOR, DisplaySubtask_MoveSelectorCursorObj},
+ {CHATDISPLAYROUTINE_SHOWQUITCHATTINGDIALOG, DisplaySubtask_ShowQuitChattingDialog},
+ {CHATDISPLAYROUTINE_DESTROYSTDMSGANDYESNO, DisplaySubtask_HideQuitChattingDialog},
+ {CHATDISPLAYROUTINE_PRINTMSG, DisplaySubtask_UpdateMessageBuffer},
+ {CHATDISPLAYROUTINE_PRINTREGISTERWHERE, DisplaySubtask_PrintRegisterWhere},
+ {CHATDISPLAYROUTINE_CANCELREGISTER, DisplaySubtask_CancelRegister},
+ {CHATDISPLAYROUTINE_RETURNTOKB, DisplaySubtask_ReturnToKeyboard},
+ {CHATDISPLAYROUTINE_SCROLLCHAT, DisplaySubtask_ScrollChat},
+ {CHATDISPLAYROUTINE_CURSORBLINK, DisplaySubtask_AnimateSelectorCursorBlink},
+ {CHATDISPLAYROUTINE_PRINTINPUTTEXT, DisplaySubtask_PrintInputText},
+ {CHATDISPLAYROUTINE_PRINTEXITINGCHAT, DisplaySubtask_PrintExitingChat},
+ {CHATDISPLAYROUTINE_PRINTLEADERLEFT, DisplaySubtask_PrintLeaderLeft},
+ {CHATDISPLAYROUTINE_ASKSAVE, DisplaySubtask_AskSave},
+ {CHATDISPLAYROUTINE_ASKOVERWRITESAVE, DisplaySubtask_AskOverwriteSave},
+ {CHATDISPLAYROUTINE_PRINTSAVING, DisplaySubtask_PrintSavingDontTurnOffPower},
+ {CHATDISPLAYROUTINE_PRINTSAVEDTHEGAME, DisplaySubtask_PrintSavedTheGame},
+ {CHATDISPLAYROUTINE_SHOWCONFIRMLEADERLEAVEDIALOG, DisplaySubtask_ShowConfirmLeaderLeaveDialog}
+};
+
+static const struct MessageWindowInfo sMessageWindowInfo[] = {
+
+ [STDMESSAGE_QUIT_CHATTING] = {
+ .text = gText_QuitChatting,
+ .boxType = 1,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = FALSE
+ },
+ [STDMESSAGE_REGISTER_WHERE] = {
+ .text = gText_RegisterTextWhere,
+ .boxType = 1,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = FALSE
+ },
+ [STDMESSAGE_REGISTER_HERE] = {
+ .text = gText_RegisterTextHere,
+ .boxType = 1,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = FALSE
+ },
+ [STDMESSAGE_INPUT_TEXT] = {
+ .text = gText_InputText,
+ .boxType = 1,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = FALSE
+ },
+ [STDMESSAGE_EXITING_CHAT] = {
+ .text = gText_ExitingTheChat,
+ .boxType = 2,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = FALSE
+ },
+ [STDMESSAGE_LEADER_LEFT] = {
+ .text = gText_LeaderHasLeftEndingChat,
+ .boxType = 2,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 0,
+ .lineSpacing = 2,
+ .expandPlaceholders = TRUE,
+ .widerBox = FALSE
+ },
+ [STDMESSAGE_ASK_SAVE] = {
+ .text = gText_RegisteredTextChanged_OKtoSave,
+ .boxType = 2,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = TRUE
+ },
+ [STDMESSAGE_ASK_OVERWRITE] = {
+ .text = gText_RegisteredTextChanged_AlreadySavedFile,
+ .boxType = 2,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = TRUE
+ },
+ [STDMESSAGE_SAVING_NO_OFF] = {
+ .text = gText_RegisteredTextChanged_SavingDontTurnOff,
+ .boxType = 2,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = TRUE
+ },
+ [STDMESSAGE_SAVED_THE_GAME] = {
+ .text = gText_RegisteredTextChanged_SavedTheGame,
+ .boxType = 2,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = TRUE,
+ .widerBox = TRUE
+ },
+ [STDMESSAGE_WARN_LEADER_LEAVE] = {
+ .text = gText_IfLeaderLeavesChatWillEnd,
+ .boxType = 2,
+ .x = 0,
+ .y = 0,
+ .letterSpacing = 1,
+ .lineSpacing = 2,
+ .expandPlaceholders = FALSE,
+ .widerBox = TRUE
+ }
+};
+
+static const u8 gText_Ellipsis[] = _("…");
+
+static const struct MenuAction sKeyboardSwapTexts[] = {
+ {gText_Upper},
+ {gText_Lower},
+ {gText_Symbols},
+ {gText_Register2},
+ {gText_Exit}
+};
+
+bool8 UnionRoomChat_TryAllocGraphicsWork(void)
+{
+ sWork = Alloc(sizeof(*sWork));
+ if (sWork && UnionRoomChat_TryAllocSpriteWork())
+ {
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gUnknown_845AA84, NELEMS(gUnknown_845AA84));
+ InitWindows(gUnknown_845AA94);
+ ResetTempTileDataBuffers();
+ sub_812AD50();
+ InitWork(sWork);
+ UnionRoomChat_ResetDisplaySubtasks();
+ UnionRoomChat_StartDisplaySubtask(0, 0);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool32 UnionRoomChat_RunDisplaySubtask0(void)
+{
+ return RunDisplaySubtask(0);
+}
+
+void UnionRoomChat_FreeGraphicsWork(void)
+{
+ UnionRoomChat_FreeSpriteWork();
+ if (sWork != NULL)
+ FREE_AND_SET_NULL(sWork);
+
+ FreeAllWindowBuffers();
+ gScanlineEffect.state = 3;
+}
+
+static void InitWork(struct UnionRoomChat2 *arg0)
+{
+ arg0->yesNoMenuWinId = 0xFF;
+ arg0->messageWindowId = 0xFF;
+ arg0->curLine = 0;
+}
+
+void UnionRoomChat_ResetDisplaySubtasks(void)
+{
+ int i;
+
+ if (sWork == NULL)
+ return;
+
+ for (i = 0; i < 3; i++)
+ {
+ sWork->subtasks[i].callback = DisplaySubtaskDummy;
+ sWork->subtasks[i].active = FALSE;
+ sWork->subtasks[i].state = 0;
+ }
+}
+
+void UnionRoomChat_RunDisplaySubtasks(void)
+{
+ int i;
+
+ if (sWork == NULL)
+ return;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (sWork->subtasks[i].active)
+ sWork->subtasks[i].active = sWork->subtasks[i].callback(&sWork->subtasks[i].state);
+ }
+}
+
+void UnionRoomChat_StartDisplaySubtask(u16 arg0, u8 arg1)
+{
+ int i;
+
+ sWork->subtasks[arg1].callback = DisplaySubtaskDummy;
+ for (i = 0; i < NELEMS(sSubtaskInfo); i++)
+ {
+ if (sSubtaskInfo[i].idx == arg0)
+ {
+ sWork->subtasks[arg1].callback = sSubtaskInfo[i].callback;
+ sWork->subtasks[arg1].active = TRUE;
+ sWork->subtasks[arg1].state = 0;
+ break;
+ }
+ }
+}
+
+bool8 RunDisplaySubtask(u8 arg0)
+{
+ return sWork->subtasks[arg0].active;
+}
+
+static bool32 DisplaySubtask_LoadGfx(u8 *state)
+{
+ if (FreeTempTileDataBuffersIfPossible() == TRUE)
+ return TRUE;
+
+ switch (*state)
+ {
+ case 0:
+ ResetGpuBgState();
+ SetBgTilemapWorkBuffers();
+ break;
+ case 1:
+ ClearBg0();
+ break;
+ case 2:
+ LoadUnionRoomChatPanelGfx();
+ break;
+ case 3:
+ LoadLinkMiscMenuGfx();
+ break;
+ case 4:
+ LoadBg1Pal8();
+ break;
+ case 5:
+ LoadWin0();
+ LoadWin2();
+ LoadWin3();
+ LoadWin1();
+ break;
+ case 6:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ UnionRoomChat_CreateSelectorCursorObj();
+ UnionRoomChat_SpawnTextEntryPointerSprites();
+ CreatePageSwitchUISprites();
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_PrintWin3(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PrintKeyboardSwapTextsOnWin3();
+ CopyWindowToVram(3, 3);
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_HideWin3(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ ClearWin3();
+ CopyWindowToVram(3, 3);
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_SwitchPages(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ UnionRoomChat_ToggleSelectorCursorObjVisibility(TRUE);
+ if (AnimateMoveBg1Right())
+ return TRUE;
+
+ PrintCurrentKeyboardPage();
+ CopyWindowToVram(2, 2);
+ break;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return TRUE;
+ break;
+ case 2:
+ if (AnimateMoveBg1Left())
+ return TRUE;
+
+ UnionRoomChat_MoveSelectorCursorObj();
+ UnionRoomChat_ToggleSelectorCursorObjVisibility(FALSE);
+ UpdateVisibleUnionRoomChatIcon();
+ return FALSE;
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_MoveSelectorCursorObj(u8 *state)
+{
+ UnionRoomChat_MoveSelectorCursorObj();
+ return FALSE;
+}
+
+static bool32 DisplaySubtask_ShowQuitChattingDialog(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaceStdMessageWindow(STDMESSAGE_QUIT_CHATTING, 0);
+ PlaceYesNoMenuAt(23, 11, 1);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_HideQuitChattingDialog(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ HideStdMessageWindow();
+ HideYesNoMenuWindow();
+ CopyBgTilemapBufferToVram(0);
+ break;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return TRUE;
+
+ DestroyStdMessageWindow();
+ DestroyYesNoMenuWindow();
+ return FALSE;
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_UpdateMessageBuffer(u8 *state)
+{
+ u32 start, length;
+ u8 *str;
+
+ switch (*state)
+ {
+ case 0:
+ UnionRoomChat_GetBufferSelectionRegion(&start, &length);
+ FillWin1Rect(start, length, PIXEL_FILL(0));
+ str = UnionRoomChat_GetMessageEntryBuffer();
+ PrintOnWin1Parameterized(0, str, TEXT_COLOR_LIGHT_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY);
+ CopyWindowToVram(1, 2);
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ UpdateVisibleUnionRoomChatIcon();
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_PrintRegisterWhere(u8 *state)
+{
+ u16 var0;
+ u8 *str;
+ u16 length;
+
+ switch (*state)
+ {
+ case 0:
+ var0 = UnionRoomChat_GetNumCharsInMessageEntryBuffer();
+ str = UnionRoomChat_GetEndOfMessageEntryBuffer();
+ length = StringLength_Multibyte(str);
+ FillWin1Rect(var0, length, PIXEL_FILL(6));
+ PrintOnWin1Parameterized(var0, str, TEXT_COLOR_TRANSPARENT, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED);
+ CopyWindowToVram(1, 2);
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ PlaceStdMessageWindow(STDMESSAGE_REGISTER_WHERE, 16);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ }
+ else
+ {
+ return TRUE;
+ }
+ break;
+ case 2:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ UnionRoomChat_UpdateObjPalCycle(1);
+ else
+ return TRUE;
+ break;
+ case 3:
+ return FALSE;
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_CancelRegister(u8 *state)
+{
+ u16 x;
+ u8 *str;
+ u16 length;
+
+ switch (*state)
+ {
+ case 0:
+ x = UnionRoomChat_GetNumCharsInMessageEntryBuffer();
+ str = UnionRoomChat_GetEndOfMessageEntryBuffer();
+ length = StringLength_Multibyte(str);
+ FillWin1Rect(x, length, PIXEL_FILL(0));
+ PrintOnWin1Parameterized(x, str, TEXT_COLOR_LIGHT_GREY, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY);
+ CopyWindowToVram(1, 2);
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ HideStdMessageWindow();
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ }
+ else
+ {
+ return TRUE;
+ }
+ break;
+ case 2:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ UnionRoomChat_UpdateObjPalCycle(0);
+ DestroyStdMessageWindow();
+ }
+ else
+ {
+ return TRUE;
+ }
+ break;
+ case 3:
+ return FALSE;
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_ReturnToKeyboard(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PrintCurrentKeyboardPage();
+ CopyWindowToVram(2, 2);
+ (*state)++;
+ break;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_ScrollChat(u8 *state)
+{
+ u16 row;
+ u8 *str;
+ u8 colorIdx;
+
+ switch (*state)
+ {
+ case 0:
+ row = sWork->curLine;
+ str = UnionRoomChat_GetLastReceivedMessage();
+ colorIdx = UnionRoomChat_GetReceivedPlayerIndex();
+ PrintTextOnWin0Colorized(row, str, colorIdx);
+ CopyWindowToVram(0, 2);
+ break;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return TRUE;
+
+ if (sWork->curLine < 9)
+ {
+ sWork->curLine++;
+ *state = 4;
+ return FALSE;
+ }
+ else
+ {
+ sWork->scrollCount = 0;
+ (*state)++;
+ }
+ // fall through
+ case 2:
+ ScrollWindow(0, 0, 5, PIXEL_FILL(1));
+ CopyWindowToVram(0, 2);
+ sWork->scrollCount++;
+ (*state)++;
+ // fall through
+ case 3:
+ if (IsDma3ManagerBusyWithBgCopy())
+ return TRUE;
+
+ if (sWork->scrollCount < 3)
+ {
+ (*state)--;
+ return TRUE;
+ }
+ break;
+ case 4:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+
+ (*state)++;
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_AnimateSelectorCursorBlink(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ UnionRoomChat_SetSelectorCursorClosedImage();
+ (*state)++;
+ break;
+ case 1:
+ return UnionRoomChat_AnimateSelectorCursorReopen();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_PrintInputText(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaceStdMessageWindow(STDMESSAGE_INPUT_TEXT, 16);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_PrintExitingChat(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaceStdMessageWindow(STDMESSAGE_EXITING_CHAT, 0);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_PrintLeaderLeft(u8 *state)
+{
+ u8 *str;
+
+ switch (*state)
+ {
+ case 0:
+ DynamicPlaceholderTextUtil_Reset();
+ str = UnionRoomChat_GetNameOfPlayerWhoDisbandedChat();
+ DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, str);
+ PlaceStdMessageWindow(STDMESSAGE_LEADER_LEFT, 0);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_AskSave(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaceStdMessageWindow(STDMESSAGE_ASK_SAVE, 0);
+ PlaceYesNoMenuAt(23, 10, 1);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_AskOverwriteSave(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaceStdMessageWindow(STDMESSAGE_ASK_OVERWRITE, 0);
+ PlaceYesNoMenuAt(23, 10, 1);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_PrintSavingDontTurnOffPower(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaceStdMessageWindow(STDMESSAGE_SAVING_NO_OFF, 0);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_PrintSavedTheGame(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ DynamicPlaceholderTextUtil_Reset();
+ DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gSaveBlock2Ptr->playerName);
+ PlaceStdMessageWindow(STDMESSAGE_SAVED_THE_GAME, 0);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtask_ShowConfirmLeaderLeaveDialog(u8 *state)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaceStdMessageWindow(STDMESSAGE_WARN_LEADER_LEAVE, 0);
+ PlaceYesNoMenuAt(23, 10, 1);
+ CopyWindowToVram(sWork->messageWindowId, 3);
+ (*state)++;
+ break;
+ case 1:
+ return IsDma3ManagerBusyWithBgCopy();
+ }
+
+ return TRUE;
+}
+
+static bool32 DisplaySubtaskDummy(u8 *arg0)
+{
+ return FALSE;
+}
+
+static void PlaceYesNoMenuAt(u8 left, u8 top, u8 initialCursorPos)
+{
+ struct WindowTemplate template;
+ template.bg = 0;
+ template.tilemapLeft = left;
+ template.tilemapTop = top;
+ template.width = 6;
+ template.height = 4;
+ template.paletteNum = 14;
+ template.baseBlock = 0x052;
+ sWork->yesNoMenuWinId = AddWindow(&template);
+ if (sWork->yesNoMenuWinId != 0xFF)
+ {
+ FillWindowPixelBuffer(sWork->yesNoMenuWinId, PIXEL_FILL(1));
+ PutWindowTilemap(sWork->yesNoMenuWinId);
+ AddTextPrinterParameterized(sWork->yesNoMenuWinId, 2, gText_Yes, 8, 2, TEXT_SPEED_FF, NULL);
+ AddTextPrinterParameterized(sWork->yesNoMenuWinId, 2, gText_No, 8, 16, TEXT_SPEED_FF, NULL);
+ DrawTextBorderOuter(sWork->yesNoMenuWinId, 1, 13);
+ Menu_InitCursor(sWork->yesNoMenuWinId, 2, 0, 2, 14, 2, initialCursorPos);
+ }
+}
+
+static void HideYesNoMenuWindow(void)
+{
+ if (sWork->yesNoMenuWinId != 0xFF)
+ {
+ ClearStdWindowAndFrameToTransparent(sWork->yesNoMenuWinId, FALSE);
+ ClearWindowTilemap(sWork->yesNoMenuWinId);
+ }
+}
+
+static void DestroyYesNoMenuWindow(void)
+{
+ if (sWork->yesNoMenuWinId != 0xFF)
+ {
+ RemoveWindow(sWork->yesNoMenuWinId);
+ sWork->yesNoMenuWinId = 0xFF;
+ }
+}
+
+s8 UnionRoomChat_ProcessInput(void)
+{
+ return Menu_ProcessInput();
+}
+
+static void PlaceStdMessageWindow(int id, u16 bg0vofs)
+{
+ const u8 *str;
+ int windowId;
+ struct WindowTemplate template;
+ template.bg = 0;
+ template.tilemapLeft = 8;
+ template.tilemapTop = 16;
+ template.width = 21;
+ template.height = 4;
+ template.paletteNum = 14;
+ template.baseBlock = 0x06A;
+ if (sMessageWindowInfo[id].widerBox)
+ {
+ template.tilemapLeft -= 7;
+ template.width += 7;
+ }
+
+ sWork->messageWindowId = AddWindow(&template);
+ windowId = sWork->messageWindowId;
+ if (sWork->messageWindowId == 0xFF)
+ return;
+
+ if (sMessageWindowInfo[id].expandPlaceholders)
+ {
+ DynamicPlaceholderTextUtil_ExpandPlaceholders(sWork->expandedPlaceholdersBuffer, sMessageWindowInfo[id].text);
+ str = sWork->expandedPlaceholdersBuffer;
+ }
+ else
+ {
+ str = sMessageWindowInfo[id].text;
+ }
+
+ ChangeBgY(0, bg0vofs * 256, 0);
+ FillWindowPixelBuffer(windowId, PIXEL_FILL(1));
+ PutWindowTilemap(windowId);
+ if (sMessageWindowInfo[id].boxType == 1)
+ {
+ DrawTextBorderInner(windowId, 0xA, 2);
+ AddTextPrinterParameterized5(
+ windowId,
+ 2,
+ str,
+ sMessageWindowInfo[id].x + 8,
+ sMessageWindowInfo[id].y + 8,
+ TEXT_SPEED_FF,
+ NULL,
+ sMessageWindowInfo[id].letterSpacing,
+ sMessageWindowInfo[id].lineSpacing);
+ }
+ else
+ {
+ DrawTextBorderOuter(windowId, 0xA, 2);
+ AddTextPrinterParameterized5(
+ windowId,
+ 2,
+ str,
+ sMessageWindowInfo[id].x,
+ sMessageWindowInfo[id].y,
+ TEXT_SPEED_FF,
+ NULL,
+ sMessageWindowInfo[id].letterSpacing,
+ sMessageWindowInfo[id].lineSpacing);
+ }
+
+ sWork->messageWindowId = windowId;
+}
+
+static void HideStdMessageWindow(void)
+{
+ if (sWork->messageWindowId != 0xFF)
+ {
+ ClearStdWindowAndFrameToTransparent(sWork->messageWindowId, FALSE);
+ ClearWindowTilemap(sWork->messageWindowId);
+ }
+
+ ChangeBgY(0, 0, 0);
+}
+
+static void DestroyStdMessageWindow(void)
+{
+ if (sWork->messageWindowId != 0xFF)
+ {
+ RemoveWindow(sWork->messageWindowId);
+ sWork->messageWindowId = 0xFF;
+ }
+}
+
+static void FillWin1Rect(u16 x, u16 width, u8 fillValue)
+{
+ FillWindowPixelRect(1, fillValue, x * 8, 1, width * 8, 14);
+}
+
+static void PrintOnWin1Parameterized(u16 x, u8 *str, u8 bgColor, u8 fgColor, u8 shadowColor)
+{
+ u8 color[3];
+ u8 strbuf[35];
+
+ if (bgColor != TEXT_COLOR_TRANSPARENT)
+ FillWin1Rect(x, UnionRoomChat_GetMessageEntryCursorPosition() - x, bgColor);
+
+ color[0] = bgColor;
+ color[1] = fgColor;
+ color[2] = shadowColor;
+ strbuf[0] = EXT_CTRL_CODE_BEGIN;
+ strbuf[1] = EXT_CTRL_CODE_MIN_LETTER_SPACING;
+ strbuf[2] = 8;
+ StringCopy(&strbuf[3], str);
+ AddTextPrinterParameterized3(1, 2, x * 8, 1, color, TEXT_SPEED_FF, strbuf);
+}
+
+static void PrintCurrentKeyboardPage(void)
+{
+ u8 page;
+ int i;
+ u16 left;
+ u16 top;
+ u8 color[3];
+ u8 str[45];
+ u8 *str2;
+
+ FillWindowPixelBuffer(2, PIXEL_FILL(15));
+ page = GetCurrentKeyboardPage();
+ color[0] = TEXT_COLOR_TRANSPARENT;
+ color[1] = TEXT_DYNAMIC_COLOR_5;
+ color[2] = TEXT_DYNAMIC_COLOR_4;
+ if (page != UNION_ROOM_KB_PAGE_COUNT)
+ {
+ str[0] = EXT_CTRL_CODE_BEGIN;
+ str[1] = EXT_CTRL_CODE_MIN_LETTER_SPACING;
+ str[2] = 8;
+
+ if (page == UNION_ROOM_KB_PAGE_EMOJI)
+ left = 6;
+ else
+ left = 8;
+ for (i = 0, top = 0; i < UNION_ROOM_KB_ROW_COUNT; i++, top += 12)
+ {
+ if (!gUnionRoomKeyboardText[page][i])
+ return;
+
+ StringCopy(&str[3], gUnionRoomKeyboardText[page][i]);
+ AddTextPrinterParameterized3(2, 0, left, top, color, TEXT_SPEED_FF, str);
+ }
+ }
+ else
+ {
+ left = 4;
+ for (i = 0, top = 0; i < 10; i++, top += 12)
+ {
+ str2 = UnionRoomChat_GetWorkRegisteredText(i);
+ if (GetStringWidth(0, str2, 0) <= 40)
+ {
+ AddTextPrinterParameterized3(2, 0, left, top, color, TEXT_SPEED_FF, str2);
+ }
+ else
+ {
+ int length = StringLength_Multibyte(str2);
+ do
+ {
+ length--;
+ StringCopyN_Multibyte(str, str2, length);
+ } while (GetStringWidth(0, str, 0) > 35);
+
+ AddTextPrinterParameterized3(2, 0, left, top, color, TEXT_SPEED_FF, str);
+ AddTextPrinterParameterized3(2, 0, left + 35, top, color, TEXT_SPEED_FF, gText_Ellipsis);
+ }
+ }
+ }
+}
+
+static bool32 AnimateMoveBg1Right(void)
+{
+ if (sWork->bg1hofs < 56)
+ {
+ sWork->bg1hofs += 12;
+ if (sWork->bg1hofs >= 56)
+ sWork->bg1hofs = 56;
+
+ if (sWork->bg1hofs < 56)
+ {
+ FillScanlineEffectWithValue1col(sWork->bg1hofs);
+ return TRUE;
+ }
+ }
+
+ FillScanlineEffectWithValue2col(sWork->bg1hofs);
+ return FALSE;
+}
+
+static bool32 AnimateMoveBg1Left(void)
+{
+ if (sWork->bg1hofs > 0)
+ {
+ sWork->bg1hofs -= 12;
+ if (sWork->bg1hofs <= 0)
+ sWork->bg1hofs = 0;
+
+ if (sWork->bg1hofs > 0)
+ {
+ FillScanlineEffectWithValue1col(sWork->bg1hofs);
+ return TRUE;
+ }
+ }
+
+ FillScanlineEffectWithValue2col(sWork->bg1hofs);
+ return FALSE;
+}
+
+static void PrintKeyboardSwapTextsOnWin3(void)
+{
+ FillWindowPixelBuffer(3, PIXEL_FILL(1));
+ DrawTextBorderOuter(3, 1, 13);
+ UnionRoomAndTradeMenuPrintOptions(3, 2, 14, 5, sKeyboardSwapTexts);
+ Menu_InitCursor(3, 2, 0, 0, 14, 5, GetCurrentKeyboardPage());
+ PutWindowTilemap(3);
+}
+
+static void ClearWin3(void)
+{
+ ClearStdWindowAndFrameToTransparent(3, FALSE);
+ ClearWindowTilemap(3);
+}
+
+static void PrintTextOnWin0Colorized(u16 row, u8 *str, u8 colorIdx)
+// colorIdx: 0 = grey, 1 = red, 2 = green, 3 = blue
+{
+ u8 color[3];
+ color[0] = TEXT_COLOR_WHITE;
+ color[1] = colorIdx * 2 + 2;
+ color[2] = colorIdx * 2 + 3;
+ FillWindowPixelRect(0, PIXEL_FILL(1), 0, row * 15, 168, 15);
+ AddTextPrinterParameterized3(0, 2, 0, row * 15, color, TEXT_SPEED_FF, str);
+}
+
+static void ResetGpuBgState(void)
+{
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON);
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(64, 240));
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(0, 144));
+ SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG0 | WININ_WIN0_BG2 | WININ_WIN0_BG3
+ | WININ_WIN0_OBJ | WININ_WIN0_CLR);
+ SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR);
+}
+
+static void SetBgTilemapWorkBuffers(void)
+{
+ SetBgTilemapBuffer(0, sWork->bg0Buffer);
+ SetBgTilemapBuffer(1, sWork->bg1Buffer);
+ SetBgTilemapBuffer(3, sWork->bg3Buffer);
+ SetBgTilemapBuffer(2, sWork->bg2Buffer);
+}
+
+static void ClearBg0(void)
+{
+ RequestDma3Fill(0, (void *)BG_CHAR_ADDR(0), 0x20, 1);
+ FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32);
+ CopyBgTilemapBufferToVram(0);
+}
+
+static void LoadUnionRoomChatPanelGfx(void)
+{
+ LoadPalette(gUnionRoomChatPanelBgPal_7, 0x70, 0x20);
+ LoadPalette(sUnionRoomChatPanelBgPal_C, 0xC0, 0x20);
+ DecompressAndCopyTileDataToVram(1, gUnionRoomChatPanelBgTiles, 0, 0, 0);
+ CopyToBgTilemapBuffer(1, gUnionRoomChatPanelBgMap, 0, 0);
+ CopyBgTilemapBufferToVram(1);
+}
+
+static void LoadLinkMiscMenuGfx(void)
+{
+ u8 *ptr;
+
+ LoadPalette(gLinkMiscMenu_Pal, 0, 0x20);
+ ptr = DecompressAndCopyTileDataToVram(2, gLinkMiscMenu_Gfx, 0, 0, 0);
+ CopyToBgTilemapBuffer(2, gLinkMiscMenu_Tilemap, 0, 0);
+ CopyBgTilemapBufferToVram(2);
+}
+
+static void LoadBg1Pal8(void)
+{
+ LoadPalette(sBg1Pal8, 0x80, 0x20);
+ RequestDma3Fill(0, (void *)BG_CHAR_ADDR(1) + 0x20, 0x20, 1);
+}
+
+static void LoadWin0(void)
+{
+ LoadPalette(sWin0PalF, 0xF0, 0x20);
+ PutWindowTilemap(0);
+ FillWindowPixelBuffer(0, PIXEL_FILL(1));
+ CopyWindowToVram(0, 3);
+}
+
+static void LoadWin2(void)
+{
+ PutWindowTilemap(2);
+ PrintCurrentKeyboardPage();
+ CopyWindowToVram(2, 3);
+}
+
+static void LoadWin1(void)
+{
+ FillWindowPixelBuffer(1, PIXEL_FILL(0));
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 3);
+}
+
+static void LoadWin3(void)
+{
+ FillWindowPixelBuffer(3, PIXEL_FILL(1));
+ TextWindow_SetUserSelectedFrame(3, 1, 0xD0);
+ TextWindow_SetStdFrame0_WithPal(3, 0xA, 0x20);
+ LoadPalette(gTMCaseMainWindowPalette, 0xE0, 0x20);
+}
+
+static void sub_812AD50(void)
+{
+ struct ScanlineEffectParams params;
+ params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
+ params.dmaDest = &REG_BG1HOFS;
+ params.initState = 1;
+ params.unused9 = 0;
+ sWork->bg1hofs = 0;
+ CpuFastFill(0, gScanlineEffectRegBuffers, sizeof(gScanlineEffectRegBuffers));
+ ScanlineEffect_SetParams(params);
+}
+
+static void FillScanlineEffectWithValue1col(s16 arg0)
+{
+ CpuFill16(arg0, gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer], 0x120);
+ CpuFill16(0, gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer] + 0x90, 0x20);
+}
+
+static void FillScanlineEffectWithValue2col(s16 arg0)
+{
+ CpuFill16(arg0, gScanlineEffectRegBuffers[0], 0x120);
+ CpuFill16(0, gScanlineEffectRegBuffers[0] + 0x90, 0x20);
+ CpuFill16(arg0, gScanlineEffectRegBuffers[0] + 0x3C0, 0x120);
+ CpuFill16(0, gScanlineEffectRegBuffers[0] + 0x450, 0x20);
+}