#include "global.h" #include "bg.h" #include "malloc.h" #include "menu.h" #include "menu_helpers.h" #include "new_menu_helpers.h" #include "string_util.h" #include "strings.h" #include "task.h" #include "text_window.h" #include "window.h" #include "sound.h" #include "palette.h" #include "constants/songs.h" struct Menu { u8 left; u8 top; s8 cursorPos; s8 minCursorPos; s8 maxCursorPos; u8 windowId; u8 fontId; u8 optionWidth; u8 optionHeight; u8 columns; u8 rows; bool8 APressMuted; }; static EWRAM_DATA struct Menu sMenu = {0}; static EWRAM_DATA u16 sTileNum = 0; static EWRAM_DATA u8 sPaletteNum = 0; static EWRAM_DATA u8 sYesNoWindowId = 0; static EWRAM_DATA u8 sTopBarWindowId = 0; static const struct TextColor gUnknown_8456618 = { .fgColor = 15, .bgColor = 1, .shadowColor = 2, }; static void WindowFunc_DrawDialogFrameWithCustomTileAndPalette(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum); static void WindowFunc_ClearDialogWindowAndFrameNullPalette(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum); static void WindowFunc_DrawStdFrameWithCustomTileAndPalette(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum); static void WindowFunc_ClearStdWindowAndFrameToTransparent(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum); static u8 MultichoiceGridComputeNewCursorPos(s8 deltaX, s8 deltaY); u8 Menu_MoveCursor(s8 cursorDelta); void DestroyYesNoMenu(void); void DrawDialogFrameWithCustomTileAndPalette(u8 windowId, bool8 copyToVram, u16 tileNum, u8 paletteNum) { sTileNum = tileNum; sPaletteNum = paletteNum; CallWindowFunction(windowId, WindowFunc_DrawDialogFrameWithCustomTileAndPalette); FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); PutWindowTilemap(windowId); if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); } // not used static void DrawDialogFrameWithCustomTile(u8 windowId, bool8 copyToVram, u16 tileNum) { sTileNum = tileNum; sPaletteNum = GetWindowAttribute(windowId, WINDOW_PALETTE_NUM); CallWindowFunction(windowId, WindowFunc_DrawDialogFrameWithCustomTileAndPalette); FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); PutWindowTilemap(windowId); if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); } static void WindowFunc_DrawDialogFrameWithCustomTileAndPalette(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum) { FillBgTilemapBufferRect(bg, sTileNum, tilemapLeft - 2, tilemapTop - 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 1, tilemapLeft - 1, tilemapTop - 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 2, tilemapLeft, tilemapTop - 1, width, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 3, tilemapLeft + width, tilemapTop - 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 4, tilemapLeft + width + 1, tilemapTop - 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 5, tilemapLeft - 2, tilemapTop, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 6, tilemapLeft - 1, tilemapTop, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 8, tilemapLeft + width, tilemapTop, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 9, tilemapLeft + width + 1, tilemapTop, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 10, tilemapLeft - 2, tilemapTop + 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 11, tilemapLeft - 1, tilemapTop + 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 12, tilemapLeft + width, tilemapTop + 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 13, tilemapLeft + width + 1, tilemapTop + 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 10), tilemapLeft - 2, tilemapTop + 2, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 11), tilemapLeft - 1, tilemapTop + 2, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 12), tilemapLeft + width, tilemapTop + 2, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 13), tilemapLeft + width + 1, tilemapTop + 2, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 5), tilemapLeft - 2, tilemapTop + 3, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 6), tilemapLeft - 1, tilemapTop + 3, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 8), tilemapLeft + width, tilemapTop + 3, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 9), tilemapLeft + width + 1, tilemapTop + 3, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum), tilemapLeft - 2, tilemapTop + 4, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 1), tilemapLeft - 1, tilemapTop + 4, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 2), tilemapLeft, tilemapTop + 4, width, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 3), tilemapLeft + width, tilemapTop + 4, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, BG_TILE_V_FLIP(sTileNum + 4), tilemapLeft + width + 1, tilemapTop + 4, 1, 1, sPaletteNum); } void ClearDialogWindowAndFrameToTransparent(u8 windowId, bool8 copyToVram) { // The palette slot doesn't matter, since the tiles are transparent. CallWindowFunction(windowId, WindowFunc_ClearDialogWindowAndFrameNullPalette); FillWindowPixelBuffer(windowId, PIXEL_FILL(0)); ClearWindowTilemap(windowId); if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); } static void WindowFunc_ClearDialogWindowAndFrameNullPalette(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum) { FillBgTilemapBufferRect(bg, 0, tilemapLeft - 2, tilemapTop - 1, width + 4, height + 2, 0); } void DrawStdFrameWithCustomTileAndPalette(u8 windowId, bool8 copyToVram, u16 baseTileNum, u8 paletteNum) { sTileNum = baseTileNum; sPaletteNum = paletteNum; CallWindowFunction(windowId, WindowFunc_DrawStdFrameWithCustomTileAndPalette); FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); PutWindowTilemap(windowId); if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); } // not used static void DrawStdFrameWithCustomTile(u8 windowId, bool8 copyToVram, u16 baseTileNum) { sTileNum = baseTileNum; sPaletteNum = GetWindowAttribute(windowId, WINDOW_PALETTE_NUM); CallWindowFunction(windowId, WindowFunc_DrawStdFrameWithCustomTileAndPalette); FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); PutWindowTilemap(windowId); if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); } static void WindowFunc_DrawStdFrameWithCustomTileAndPalette(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum) { FillBgTilemapBufferRect(bg, sTileNum, tilemapLeft - 1, tilemapTop - 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 1, tilemapLeft, tilemapTop - 1, width, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 2, tilemapLeft + width, tilemapTop - 1, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 3, tilemapLeft - 1, tilemapTop, 1, height, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 5, tilemapLeft + width, tilemapTop, 1, height, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 6, tilemapLeft - 1, tilemapTop + height, 1, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 7, tilemapLeft, tilemapTop + height, width, 1, sPaletteNum); FillBgTilemapBufferRect(bg, sTileNum + 8, tilemapLeft + width, tilemapTop + height, 1, 1, sPaletteNum); } void ClearStdWindowAndFrameToTransparent(u8 windowId, bool8 copyToVram) { CallWindowFunction(windowId, WindowFunc_ClearStdWindowAndFrameToTransparent); FillWindowPixelBuffer(windowId, PIXEL_FILL(0)); ClearWindowTilemap(windowId); if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); } static void WindowFunc_ClearStdWindowAndFrameToTransparent(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum) { FillBgTilemapBufferRect(bg, 0, tilemapLeft - 1, tilemapTop - 1, width + 2, height + 2, 0); } /* The following functions are used for handling top bar window in hall of fame screen and story mode screen before oak intro. However, you can still designate a yPos value to place that bar as well as the bar width. The xPos is simply computed according to width (always right aligned). */ u8 CreateTopBarWindowLoadPalette(u8 bg, u8 width, u8 yPos, u8 palette, u16 baseTile) { struct WindowTemplate window; memset(&window, 0, sizeof(window)); if (bg > 3) window.bg = 0; else window.bg = bg; window.tilemapTop = yPos; window.height = 2; window.tilemapLeft = 0x1E - width; window.width = width; window.paletteNum = palette; window.baseBlock = baseTile; sTopBarWindowId = AddWindow(&window); if (palette > 15) palette = 15 * 16; else palette *= 16; LoadPalette(stdpal_get(2), palette, 0x20); return sTopBarWindowId; } void TopBarWindowPrintString(const u8 *string, u8 unUsed, bool8 copyToVram) { s32 width; if (sTopBarWindowId != 0xFF) { PutWindowTilemap(sTopBarWindowId); FillWindowPixelBuffer(sTopBarWindowId, PIXEL_FILL(15)); width = GetStringWidth(0, string, 0); AddTextPrinterParameterized3(sTopBarWindowId, 0, -20 - width, 1, &gUnknown_8456618, 0, string); if (copyToVram) CopyWindowToVram(sTopBarWindowId, 3); } } void TopBarWindowPrintTwoStrings(const u8 *string, const u8 *string2, bool8 fgColorChooser, u8 notUsed, bool8 copyToVram) { struct TextColor color; s32 fgColor, width; if ( sTopBarWindowId != 0xFF ) { if (fgColorChooser) { color.fgColor = 0; color.bgColor = 1; color.shadowColor = 2; } else { color.fgColor = 15; color.bgColor = 1; color.shadowColor = 2; } PutWindowTilemap(sTopBarWindowId); FillWindowPixelBuffer(sTopBarWindowId, PIXEL_FILL(15)); if (string2) { width = GetStringWidth(0, string2, 0); AddTextPrinterParameterized3(sTopBarWindowId, 0, -20 - width, 1, &color, 0, string2); } AddTextPrinterParameterized4(sTopBarWindowId, 1, 4, 1, 0, 0, &color, 0, string); if (copyToVram) CopyWindowToVram(sTopBarWindowId, 3); } } // not used static void Unused_CopyTopBarWindowToVram(void) { if (sTopBarWindowId != 0xFF) CopyWindowToVram(sTopBarWindowId, 3); } void ClearTopBarWindow(void) { if (sTopBarWindowId != 0xFF) { FillWindowPixelBuffer(sTopBarWindowId, PIXEL_FILL(15)); CopyWindowToVram(sTopBarWindowId, 3); } } void DestroyTopBarWindow(void) { if (sTopBarWindowId != 0xFF) { FillWindowPixelBuffer(sTopBarWindowId, PIXEL_FILL(0)); ClearWindowTilemap(sTopBarWindowId); CopyWindowToVram(sTopBarWindowId, 3); RemoveWindow(sTopBarWindowId); sTopBarWindowId = 0xFF; } } u8 Menu_InitCursorInternal(u8 windowId, u8 fontId, u8 left, u8 top, u8 cursorHeight, u8 numChoices, u8 initialCursorPos, bool8 APressMuted) { s32 pos; sMenu.left = left; sMenu.top = top; sMenu.minCursorPos = 0; sMenu.maxCursorPos = numChoices - 1; sMenu.windowId = windowId; sMenu.fontId = fontId; sMenu.optionHeight = cursorHeight; sMenu.APressMuted = APressMuted; pos = initialCursorPos; if (pos < 0 || pos > sMenu.maxCursorPos) sMenu.cursorPos = 0; else sMenu.cursorPos = pos; Menu_MoveCursor(0); return sMenu.cursorPos; } u8 Menu_InitCursor(u8 windowId, u8 fontId, u8 left, u8 top, u8 cursorHeight, u8 numChoices, u8 initialCursorPos) { return Menu_InitCursorInternal(windowId, fontId, left, top, cursorHeight, numChoices, initialCursorPos, 0); } // not used static u8 sub_810F818(u8 windowId, u8 fontId, u8 left, u8 top, u8 numChoices, u8 initialCursorPos) { return Menu_InitCursor(windowId, fontId, left, top, GetMenuCursorDimensionByFont(fontId, 1), numChoices, initialCursorPos); } void RedrawMenuCursor(u8 oldPos, u8 newPos) { u8 width, height; width = GetMenuCursorDimensionByFont(sMenu.fontId, 0); height = GetMenuCursorDimensionByFont(sMenu.fontId, 1); FillWindowPixelRect(sMenu.windowId, 1, sMenu.left, sMenu.optionHeight * oldPos + sMenu.top, width, height); AddTextPrinterParameterized(sMenu.windowId, sMenu.fontId, gFameCheckerText_ListMenuCursor, sMenu.left, sMenu.optionHeight * newPos + sMenu.top, 0, 0); } u8 Menu_MoveCursor(s8 cursorDelta) { u8 oldPos = sMenu.cursorPos; s32 newPos = sMenu.cursorPos + cursorDelta; if (newPos < sMenu.minCursorPos) sMenu.cursorPos = sMenu.maxCursorPos; else if (newPos > sMenu.maxCursorPos) sMenu.cursorPos = sMenu.minCursorPos; else sMenu.cursorPos += cursorDelta; RedrawMenuCursor(oldPos, sMenu.cursorPos); return sMenu.cursorPos; } u8 Menu_MoveCursorNoWrapAround(s8 cursorDelta) { u8 oldPos = sMenu.cursorPos; s32 newPos = sMenu.cursorPos + cursorDelta; if (newPos < sMenu.minCursorPos) sMenu.cursorPos = sMenu.minCursorPos; else if (newPos > sMenu.maxCursorPos) sMenu.cursorPos = sMenu.maxCursorPos; else sMenu.cursorPos += cursorDelta; RedrawMenuCursor(oldPos, sMenu.cursorPos); return sMenu.cursorPos; } u8 Menu_GetCursorPos(void) { return sMenu.cursorPos; } s8 Menu_ProcessInput(void) { if (JOY_NEW(A_BUTTON)) { if (!sMenu.APressMuted) PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_NEW(DPAD_UP)) { PlaySE(SE_SELECT); Menu_MoveCursor(-1); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_DOWN)) { PlaySE(SE_SELECT); Menu_MoveCursor(1); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; } s8 Menu_ProcessInputNoWrapAround(void) { u8 oldPos = sMenu.cursorPos; if (JOY_NEW(A_BUTTON)) { if (!sMenu.APressMuted) PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_NEW(DPAD_UP)) { if (oldPos != Menu_MoveCursorNoWrapAround(-1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_DOWN)) { if (oldPos != Menu_MoveCursorNoWrapAround(1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; } s8 Menu_ProcessInput_other(void) { if (JOY_NEW(A_BUTTON)) { if (!sMenu.APressMuted) PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_REPT(DPAD_ANY) == DPAD_UP) { PlaySE(SE_SELECT); Menu_MoveCursor(-1); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_DOWN) { PlaySE(SE_SELECT); Menu_MoveCursor(1); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; } s8 Menu_ProcessInputNoWrapAround_other(void) { u8 oldPos = sMenu.cursorPos; if (JOY_NEW(A_BUTTON)) { if (!sMenu.APressMuted) PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_REPT(DPAD_ANY) == DPAD_UP) { if (oldPos != Menu_MoveCursorNoWrapAround(-1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_DOWN) { if (oldPos != Menu_MoveCursorNoWrapAround(1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; } void PrintTextArray(u8 windowId, u8 fontId, u8 left, u8 top, u8 lineHeight, u8 itemCount, const struct MenuAction *strs) { u8 i; for (i = 0; i < itemCount; i++) AddTextPrinterParameterized(windowId, fontId, strs[i].text, left, (lineHeight * i) + top, 0xFF, NULL); CopyWindowToVram(windowId, 2); } void PrintMultichoiceListItems(u8 windowId, u8 fontId, u8 left, u8 top, u8 lineHeight, u8 itemCount, const struct MenuAction *strs, u8 letterSpacing, u8 lineSpacing) { u8 i; for (i = 0; i < itemCount; i++) { AddTextPrinterParameterized5(windowId, fontId, strs[i].text, left, (lineHeight * i) + top, 0xFF, NULL, letterSpacing, lineSpacing); } CopyWindowToVram(windowId, 2); } void UnionRoomAndTradeMenuPrintOptions(u8 windowId, u8 fontId, u8 lineHeight, u8 itemCount, const struct MenuAction *strs) { u8 left = GetMenuCursorDimensionByFont(fontId, 0); PrintTextArray(windowId, fontId, left, 0, lineHeight, itemCount, strs); } void AddItemMenuActionTextPrinters(u8 windowId, u8 fontId, u8 left, u8 top, u8 letterSpacing, u8 lineHeight, u8 itemCount, const struct MenuAction *strs, const u8 *orderArray) { u8 i; struct TextPrinterTemplate printer; printer.windowId = windowId; printer.fontId = fontId; printer.fgColor = GetFontAttribute(fontId, FONTATTR_COLOR_FOREGROUND); printer.bgColor = GetFontAttribute(fontId, FONTATTR_COLOR_BACKGROUND); printer.shadowColor = GetFontAttribute(fontId, FONTATTR_COLOR_SHADOW); printer.unk = GetFontAttribute(fontId, FONTATTR_UNKNOWN); printer.letterSpacing = letterSpacing; printer.lineSpacing = GetFontAttribute(fontId, FONTATTR_LINE_SPACING); printer.x = left; printer.currentX = left; for (i = 0; i < itemCount; i++) { printer.currentChar = strs[orderArray[i]].text; printer.y = (lineHeight * i) + top; printer.currentY = printer.y; AddTextPrinter(&printer, 0xFF, NULL); } CopyWindowToVram(windowId, 2); } // not used static void sub_810FDE4(u8 windowId, u8 fontId, u8 lineHeight, u8 itemCount, const struct MenuAction *strs, const u8 *orderArray) { AddItemMenuActionTextPrinters(windowId, fontId, GetFontAttribute(fontId, FONTATTR_MAX_LETTER_WIDTH), 0, GetFontAttribute(fontId, FONTATTR_LETTER_SPACING), lineHeight, itemCount, strs, orderArray); } /* struct WindowTemplateWithAttr SetWindowTemplateFields(struct WindowTemplate *template, u8 bg, u8 left, u8 top, u8 width, u8 height, u8 paletteNum, u16 baseBlock) { struct WindowTemplate temp; struct WindowTemplateWithAttr ret; temp.bg = bg; temp.tilemapLeft = left; temp.tilemapTop = top; temp.width = width; temp.height = height; temp.paletteNum = paletteNum; temp.baseBlock = baseBlock; *template = temp; ret.ptr = template; ret.attr = *((u32*)&temp); return ret; } */ NAKED void SetWindowTemplateFields(struct WindowTemplate *template, u8 bg, u8 left, u8 top, u8 width, u8 height, u8 paletteNum, u16 baseBlock) { asm_unified("\n\ push {r4-r7,lr}\n\ mov r7, r10\n\ mov r6, r9\n\ mov r5, r8\n\ push {r5-r7}\n\ sub sp, 0x8\n\ ldr r4, [sp, 0x28]\n\ mov r12, r4\n\ ldr r4, [sp, 0x2C]\n\ mov r9, r4\n\ ldr r4, [sp, 0x30]\n\ mov r10, r4\n\ ldr r7, [sp, 0x34]\n\ lsls r1, 24\n\ lsrs r1, 24\n\ lsls r2, 24\n\ lsls r3, 24\n\ mov r4, r9\n\ lsls r4, 24\n\ lsrs r4, 24\n\ mov r9, r4\n\ mov r4, r10\n\ lsls r4, 24\n\ mov r10, r4\n\ ldr r4, _0810FEF0 @ =0xffffff00\n\ mov r8, r4\n\ mov r5, r8\n\ ldr r4, [sp]\n\ ands r5, r4\n\ orrs r5, r1\n\ str r5, [sp]\n\ lsrs r2, 16\n\ ldr r6, _0810FEF4 @ =0xffff00ff\n\ adds r4, r6, 0\n\ ands r4, r5\n\ orrs r4, r2\n\ str r4, [sp]\n\ lsrs r3, 8\n\ ldr r1, _0810FEF8 @ =0xff00ffff\n\ ands r1, r4\n\ orrs r1, r3\n\ str r1, [sp]\n\ mov r2, r12\n\ lsls r2, 24\n\ mov r12, r2\n\ ldr r2, _0810FEFC @ =0x00ffffff\n\ ands r1, r2\n\ mov r4, r12\n\ orrs r4, r1\n\ str r4, [sp]\n\ ldr r1, [sp, 0x4]\n\ mov r2, r8\n\ ands r1, r2\n\ mov r4, r9\n\ orrs r1, r4\n\ mov r8, r1\n\ str r1, [sp, 0x4]\n\ mov r1, r10\n\ lsrs r1, 16\n\ mov r2, r8\n\ ands r6, r2\n\ orrs r6, r1\n\ str r6, [sp, 0x4]\n\ lsls r2, r7, 16\n\ ldr r1, _0810FF00 @ =0x0000ffff\n\ ands r6, r1\n\ orrs r6, r2\n\ str r6, [sp, 0x4]\n\ ldr r1, [sp]\n\ ldr r2, [sp, 0x4]\n\ str r1, [r0]\n\ str r2, [r0, 0x4]\n\ add sp, 0x8\n\ pop {r3-r5}\n\ mov r8, r3\n\ mov r9, r4\n\ mov r10, r5\n\ pop {r4-r7}\n\ pop {r2}\n\ bx r2\n\ .align 2, 0\n\ _0810FEF0: .4byte 0xffffff00\n\ _0810FEF4: .4byte 0xffff00ff\n\ _0810FEF8: .4byte 0xff00ffff\n\ _0810FEFC: .4byte 0x00ffffff\n\ _0810FF00: .4byte 0x0000ffff\n\ "); } // not used static u16 CreateWindowTemplate(u8 bg, u8 left, u8 top, u8 width, u8 height, u8 paletteNum, u16 baseBlock) { struct WindowTemplate template, temp; SetWindowTemplateFields(&template, bg, left, top, width, height, paletteNum, baseBlock); temp = template; return (u16)AddWindow(&temp); } void CreateYesNoMenu(const struct WindowTemplate *window, u8 fontId, u8 left, u8 top, u16 baseTileNum, u8 paletteNum, u8 initialCursorPos) { struct TextPrinterTemplate textSubPrinter; sYesNoWindowId = AddWindow(window); DrawStdFrameWithCustomTileAndPalette(sYesNoWindowId, 1, baseTileNum, paletteNum); textSubPrinter.currentChar = gUnknown_841623D; textSubPrinter.windowId = sYesNoWindowId; textSubPrinter.fontId = fontId; textSubPrinter.x = GetMenuCursorDimensionByFont(fontId, 0) + left; textSubPrinter.y = top; textSubPrinter.currentX = textSubPrinter.x; textSubPrinter.currentY = textSubPrinter.y; textSubPrinter.fgColor = GetFontAttribute(fontId, FONTATTR_COLOR_FOREGROUND); textSubPrinter.bgColor = GetFontAttribute(fontId, FONTATTR_COLOR_BACKGROUND); textSubPrinter.shadowColor = GetFontAttribute(fontId, FONTATTR_COLOR_SHADOW); textSubPrinter.unk = GetFontAttribute(fontId, FONTATTR_UNKNOWN); textSubPrinter.letterSpacing = GetFontAttribute(fontId, FONTATTR_LETTER_SPACING); textSubPrinter.lineSpacing = GetFontAttribute(fontId, FONTATTR_LINE_SPACING); AddTextPrinter(&textSubPrinter, 0xFF, NULL); Menu_InitCursor(sYesNoWindowId, fontId, left, top, GetFontAttribute(fontId, FONTATTR_MAX_LETTER_HEIGHT) + textSubPrinter.lineSpacing, 2, initialCursorPos); } // not used static void Unused_CreateYesNoMenu2(const struct WindowTemplate *window, u8 paletteNum, u16 baseTileNum, u8 initialCursorPos) { CreateYesNoMenu(window, paletteNum, 0, 0, baseTileNum, initialCursorPos, 0); } s8 Menu_ProcessInputNoWrapClearOnChoose(void) { s8 result = Menu_ProcessInputNoWrapAround(); if (result != MENU_NOTHING_CHOSEN) DestroyYesNoMenu(); return result; } void DestroyYesNoMenu(void) { ClearStdWindowAndFrameToTransparent(sYesNoWindowId, TRUE); RemoveWindow(sYesNoWindowId); } void MultichoiceGridPrintItems(u8 windowId, u8 fontId, u8 itemWidth, u8 itemHeight, u8 cols, u8 rows, const struct MenuAction *strs) { u8 width, i, j, yOffset; fontId = fontId; itemWidth = itemWidth; itemHeight = itemHeight; width = GetFontAttribute(fontId, FONTATTR_MAX_LETTER_WIDTH); yOffset = (16 - GetFontAttribute(fontId, FONTATTR_MAX_LETTER_HEIGHT)) / 2; for (i = 0; i < rows; ++i) for (j = 0; j < cols; ++j) AddTextPrinterParameterized(windowId, fontId, strs[i * cols + j].text, itemWidth * j + width, yOffset + itemHeight * i, 0xFF, 0); CopyWindowToVram(windowId, 2); } //not used static void Unused_MultichoiceGridPrintItemsCustomOrder(u8 windowId, u8 fontId, u8 itemWidth, u8 itemHeight, u8 cols, u8 rows, const struct MenuAction *strs, const u8 *orderArray) { u8 width, i, j; fontId = fontId; itemWidth = itemWidth; itemHeight = itemHeight; width = GetFontAttribute(fontId, FONTATTR_MAX_LETTER_WIDTH); for (i = 0; i < rows; ++i) for (j = 0; j < cols; ++j) AddTextPrinterParameterized(windowId, fontId, strs[orderArray[i * cols + j]].text, itemWidth * j + width, itemHeight * i, 0xFF, 0); CopyWindowToVram(windowId, 2); } static u8 MultichoiceGridInitCursorInternal(u8 windowId, u8 fontId, u8 left, u8 top, u8 optionWidth, u8 cursorHeight, u8 cols, u8 rows, u8 numChoices, u8 cursorPos) { s32 pos; sMenu.left = left; sMenu.top = top; sMenu.minCursorPos = 0; sMenu.maxCursorPos = numChoices - 1; sMenu.windowId = windowId; sMenu.fontId = fontId; sMenu.optionWidth = optionWidth; sMenu.optionHeight = cursorHeight; sMenu.columns = cols; sMenu.rows = rows; pos = cursorPos; if (pos < 0 || pos > sMenu.maxCursorPos) sMenu.cursorPos = 0; else sMenu.cursorPos = pos; MultichoiceGridComputeNewCursorPos(0, 0); return sMenu.cursorPos; } u8 MultichoiceGridInitCursor(u8 windowId, u8 fontId, u8 left, u8 top, u8 optionWidth, u8 cols, u8 rows, u8 cursorPos) { s32 cursorHeight = 16; u8 numChoices = cols * rows; return MultichoiceGridInitCursorInternal(windowId, fontId, left, top, optionWidth, cursorHeight, cols, rows, numChoices, cursorPos); } static void MultichoiceGridUpdateCursorPos(u8 oldCursorPos, u8 newCursorPos) { u8 cursorWidth = GetMenuCursorDimensionByFont(sMenu.fontId, 0); u8 cursorHeight = GetMenuCursorDimensionByFont(sMenu.fontId, 1); u8 xPos = (oldCursorPos % sMenu.columns) * sMenu.optionWidth + sMenu.left; u8 yPos = (oldCursorPos / sMenu.columns) * sMenu.optionHeight + sMenu.top; FillWindowPixelRect(sMenu.windowId, PIXEL_FILL(1), xPos, yPos, cursorWidth, cursorHeight); xPos = (newCursorPos % sMenu.columns) * sMenu.optionWidth + sMenu.left; yPos = (newCursorPos / sMenu.columns) * sMenu.optionHeight + sMenu.top; AddTextPrinterParameterized(sMenu.windowId, sMenu.fontId, gFameCheckerText_ListMenuCursor, xPos, yPos, 0, 0); } static u8 MultichoiceGridComputeNewCursorPos(s8 deltaX, s8 deltaY) { u8 oldPos = sMenu.cursorPos; if (deltaX) { if ((sMenu.cursorPos % sMenu.columns) + deltaX < 0) sMenu.cursorPos += sMenu.columns - 1; else if ((sMenu.cursorPos % sMenu.columns) + deltaX >= sMenu.columns) sMenu.cursorPos = (sMenu.cursorPos / sMenu.columns) * sMenu.columns; else sMenu.cursorPos += deltaX; } if (deltaY) { if ((sMenu.cursorPos / sMenu.columns) + deltaY < 0) sMenu.cursorPos += sMenu.columns * (sMenu.rows - 1); else if ((sMenu.cursorPos / sMenu.columns) + deltaY >= sMenu.rows) sMenu.cursorPos -= sMenu.columns * (sMenu.rows - 1); else sMenu.cursorPos += (sMenu.columns * deltaY); } if (sMenu.cursorPos > sMenu.maxCursorPos) { sMenu.cursorPos = oldPos; return sMenu.cursorPos; } else { MultichoiceGridUpdateCursorPos(oldPos, sMenu.cursorPos); return sMenu.cursorPos; } } static u8 MultichoiceGridComputeNewCursorPosIfValid(s8 deltaX, s8 deltaY) { u8 oldPos = sMenu.cursorPos; if (deltaX) { if (((sMenu.cursorPos % sMenu.columns) + deltaX >= 0) && ((sMenu.cursorPos % sMenu.columns) + deltaX < sMenu.columns)) sMenu.cursorPos += deltaX; } if (deltaY) { if (((sMenu.cursorPos / sMenu.columns) + deltaY >= 0) && ((sMenu.cursorPos / sMenu.columns) + deltaY < sMenu.rows)) sMenu.cursorPos += (sMenu.columns * deltaY); } if (sMenu.cursorPos > sMenu.maxCursorPos) { sMenu.cursorPos = oldPos; return sMenu.cursorPos; } else { MultichoiceGridUpdateCursorPos(oldPos, sMenu.cursorPos); return sMenu.cursorPos; } } // not used static s8 sub_81105A0(void) { if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_NEW(DPAD_UP)) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(0, -1); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_DOWN)) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(0, 1); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_LEFT) || GetLRKeysState() == 1) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(-1, 0); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_RIGHT) || GetLRKeysState() == 2) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(1, 0); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; } s8 Menu_ProcessInputGridLayout(void) { u8 oldPos = sMenu.cursorPos; if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_NEW(DPAD_UP)) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(0, -1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_DOWN)) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(0, 1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_LEFT) || GetLRKeysState() == 1) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(-1, 0)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_NEW(DPAD_RIGHT) || GetLRKeysState() == 2) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(1, 0)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; } // not used static s8 sub_81106F4(void) { if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_REPT(DPAD_ANY) == DPAD_UP) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(0, -1); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_DOWN) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(0, 1); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_LEFT || sub_80BF66C() == 1) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(-1, 0); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_RIGHT || sub_80BF66C() == 2) { PlaySE(SE_SELECT); MultichoiceGridComputeNewCursorPos(1, 0); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; } // not used static s8 sub_81107A0(void) { u8 oldPos = sMenu.cursorPos; if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); return sMenu.cursorPos; } else if (JOY_NEW(B_BUTTON)) { return MENU_B_PRESSED; } else if (JOY_REPT(DPAD_ANY) == DPAD_UP) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(0, -1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_DOWN) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(0, 1)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_LEFT || sub_80BF66C() == 1) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(-1, 0)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } else if (JOY_REPT(DPAD_ANY) == DPAD_RIGHT || sub_80BF66C() == 2) { if (oldPos != MultichoiceGridComputeNewCursorPosIfValid(1, 0)) PlaySE(SE_SELECT); return MENU_NOTHING_CHOSEN; } return MENU_NOTHING_CHOSEN; }