#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 InitScanlineEffect(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(); InitScanlineEffect(); 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, COPYWIN_BOTH); break; case 1: return IsDma3ManagerBusyWithBgCopy(); } (*state)++; return TRUE; } static bool32 DisplaySubtask_HideWin3(u8 *state) { switch (*state) { case 0: ClearWin3(); CopyWindowToVram(3, COPYWIN_BOTH); 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, COPYWIN_GFX); 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, COPYWIN_BOTH); 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_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY); CopyWindowToVram(1, COPYWIN_GFX); 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, COPYWIN_GFX); break; case 1: if (!IsDma3ManagerBusyWithBgCopy()) { PlaceStdMessageWindow(STDMESSAGE_REGISTER_WHERE, 16); CopyWindowToVram(sWork->messageWindowId, COPYWIN_BOTH); } 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_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY); CopyWindowToVram(1, COPYWIN_GFX); break; case 1: if (!IsDma3ManagerBusyWithBgCopy()) { HideStdMessageWindow(); CopyWindowToVram(sWork->messageWindowId, COPYWIN_BOTH); } 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, COPYWIN_GFX); (*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, COPYWIN_GFX); 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, COPYWIN_GFX); 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, COPYWIN_BOTH); (*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, COPYWIN_BOTH); (*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, COPYWIN_BOTH); (*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, COPYWIN_BOTH); (*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, COPYWIN_BOTH); (*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, COPYWIN_BOTH); (*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, COPYWIN_BOTH); (*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, COPYWIN_BOTH); (*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, DMA3_32BIT); 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, DMA3_32BIT); } static void LoadWin0(void) { LoadPalette(sWin0PalF, 0xF0, 0x20); PutWindowTilemap(0); FillWindowPixelBuffer(0, PIXEL_FILL(1)); CopyWindowToVram(0, COPYWIN_BOTH); } static void LoadWin2(void) { PutWindowTilemap(2); PrintCurrentKeyboardPage(); CopyWindowToVram(2, COPYWIN_BOTH); } static void LoadWin1(void) { FillWindowPixelBuffer(1, PIXEL_FILL(0)); PutWindowTilemap(1); CopyWindowToVram(1, COPYWIN_BOTH); } 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 InitScanlineEffect(void) { struct ScanlineEffectParams params; params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; params.dmaDest = ®_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); }