summaryrefslogtreecommitdiff
path: root/src/engine/text.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/text.c')
-rw-r--r--src/engine/text.c4324
1 files changed, 4324 insertions, 0 deletions
diff --git a/src/engine/text.c b/src/engine/text.c
new file mode 100644
index 000000000..abde4484a
--- /dev/null
+++ b/src/engine/text.c
@@ -0,0 +1,4324 @@
+#include "global.h"
+#include "text.h"
+#include "battle.h"
+#include "main.h"
+#include "palette.h"
+#include "songs.h"
+#include "sound.h"
+#include "string_util.h"
+
+enum
+{
+ WIN_STATE_END,
+ WIN_STATE_BEGIN,
+ WIN_STATE_NORMAL,
+ WIN_STATE_INTERRUPTIBLE_PAUSE,
+ WIN_STATE_PAUSE,
+ WIN_STATE_WAIT_BUTTON,
+ WIN_STATE_NEWLINE,
+ WIN_STATE_PLACEHOLDER,
+ WIN_STATE_PARAGRAPH,
+ WIN_STATE_NEWLINE_WAIT,
+ WIN_STATE_WAIT_SOUND,
+};
+
+struct Font
+{
+ u32 type;
+ u8 *glyphs;
+ u16 glyphSize;
+ u16 lowerTileOffset;
+};
+
+struct GlyphBuffer
+{
+ // 0-7 left tile
+ // 8-15 right tile (if it exists)
+ u32 pixelRows[16];
+
+ // pixel row filled with BG color
+ u32 background;
+
+ // table of color indices (not a palette)
+ u32 colors[16];
+};
+
+struct GlyphTileInfo
+{
+ u8 textMode;
+ u8 startPixel;
+ u8 width;
+ u8 *src;
+ u32 *dest;
+ u32 *colors;
+};
+
+struct ShiftAmount
+{
+ u32 left;
+ u32 right;
+};
+
+static u16 InitVariableWidthFontTileData(struct Window *, u16);
+static u16 LoadFixedWidthFont(struct Window *, u16);
+static u16 LoadFixedWidthFont_Font1Latin(struct Window *, u16);
+static u16 LoadFixedWidthFont_Font4Latin(struct Window *, u16);
+static u16 LoadFixedWidthFont_Braille(struct Window *, u16);
+static void MultistepLoadFont_LoadGlyph(struct Window *, u16, u8);
+static u8 sub_8002FA0(struct Window *, const u8 *);
+static u8 InterpretText(struct Window *);
+static u8 HandleExtCtrlCode(struct Window *);
+static u8 UpdateWindowText(struct Window *);
+static u8 DrawGlyph_TextMode0(struct Window *, u32);
+static void DrawGlyph_TextMode2(struct Window *, u32);
+static void LoadFixedWidthGlyph(struct Window *, u32, u8 *);
+static void WriteGlyphTilemap(struct Window *, u16, u16);
+static void GetGlyphTilePointers(u8, u8, u16, u8 **, u8 **);
+static u16 *GetCursorTilemapPointer(struct Window *);
+static void ApplyColors_UnshadowedFont(const u8 *, u32 *, u8, u8);
+static void ApplyColors_ShadowedFont(const void *, void *, u8, u8, u8);
+static void SetCursorX(struct Window *, u8);
+static void AddToCursorX(struct Window *, u8);
+static void AddToCursorY(struct Window *, u8);
+static void ClipLeft(struct Window *);
+static void ClipRight(struct Window *);
+static void InitColors(struct Window *);
+static void SetBackgroundColor(struct Window *, u8);
+static void SetShadowColor(struct Window *, u8);
+static void SetForegroundColor(struct Window *, u8);
+static u8 GetTextDelay(struct Window *);
+static bool8 PlayerCanInterruptWait(struct Window *);
+static void ScrollWindowTextLines(struct Window *);
+static void ScrollWindowTextLines_TextMode0(struct Window *);
+static void DoScroll_TextMode0(struct Window *, u16);
+static void ScrollWindowTextLines_TextMode1(struct Window *);
+static void DoScroll_TextMode1(struct Window *, u16);
+static void ScrollWindowTextLines_TextMode2(struct Window *);
+static void DoScroll_TextMode2(struct Window *, u8);
+void ClearWindowTextLines(struct Window *);
+static void ClearWindowTextLines_TextMode0_TextMode1(struct Window *, u8);
+static void ClearWindowTextLines_TextMode2(struct Window *, u8);
+static void TryEraseDownArrow(struct Window *);
+static u16 GetBlankTileNum(struct Window *);
+static u8 WaitWithDownArrow(struct Window *);
+static void DrawInitialDownArrow(struct Window *);
+static void DrawMovingDownArrow(struct Window *);
+static u16 GetCursorTileNum(struct Window *, u32, u32);
+static s32 DrawGlyphTiles(struct Window *, u32, u32);
+static void UpdateTilemap(struct Window *, u32);
+static u8 GetGlyphWidth(struct Window *, u32);
+static s32 DrawGlyphTile_ShadowedFont(struct GlyphTileInfo *);
+
+static void PrintGlyph_TextMode0(struct Window *, u32);
+static void PrintGlyph_TextMode1(struct Window *, u32);
+static void PrintGlyph_TextMode2(struct Window *, u32);
+
+static void WriteGlyphTilemap_Font0_Font3(struct Window *, u32);
+static void WriteGlyphTilemap_Font1_Font4(struct Window *, u32);
+static void WriteGlyphTilemap_Font2_Font5(struct Window *, u32);
+static void WriteGlyphTilemap_Font1_Font4(struct Window *, u32);
+static void WriteGlyphTilemap_Font2_Font5(struct Window *, u32);
+static void WriteGlyphTilemap_Font6(struct Window *, u32);
+
+static u8 ExtCtrlCode_Nop(struct Window *);
+static u8 ExtCtrlCode_ForegroundColor(struct Window *);
+static u8 ExtCtrlCode_BackgroundColor(struct Window *);
+static u8 ExtCtrlCode_ShadowColor(struct Window *);
+static u8 ExtCtrlCode_AllColors(struct Window *);
+static u8 ExtCtrlCode_Palette(struct Window *);
+static u8 ExtCtrlCode_Font(struct Window *);
+static u8 ExtCtrlCode_DefaultFont(struct Window *);
+static u8 ExtCtrlCode_Pause(struct Window *);
+static u8 ExtCtrlCode_WaitButton(struct Window *);
+static u8 ExtCtrlCode_WaitSound(struct Window *);
+static u8 ExtCtrlCode_PlayBGM(struct Window *);
+static u8 ExtCtrlCode_Escape(struct Window *);
+static u8 ExtCtrlCode_Nop2(struct Window *);
+static u8 ExtCtrlCode_SetCursorY(struct Window *);
+static u8 ExtCtrlCode_ClearWindowTextLines(struct Window *);
+static u8 ExtCtrlCode_PlaySE(struct Window *);
+static u8 ExtCtrlCode_Skip(struct Window *);
+static u8 ExtCtrlCode_SetCursorX(struct Window *);
+static u8 ExtCtrlCode_SkipTo(struct Window *);
+static u8 ExtCtrlCode_Spacing(struct Window *);
+static u8 ExtCtrlCode_Japanese(struct Window *);
+static u8 ExtCtrlCode_Latin(struct Window *);
+
+static void ShiftGlyphTile_UnshadowedFont_Width0(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width1(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width2(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width3(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width4(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width5(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width6(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width7(struct GlyphBuffer *, u8 *, u32 *, u8);
+static void ShiftGlyphTile_UnshadowedFont_Width8(struct GlyphBuffer *, u8 *, u32 *, u8);
+
+static void ShiftGlyphTile_ShadowedFont_Width0(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width1(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width2(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width3(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width4(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width5(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width6(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width7(struct GlyphBuffer *, u32 *, u32 *, u8);
+static void ShiftGlyphTile_ShadowedFont_Width8(struct GlyphBuffer *, u32 *, u32 *, u8);
+
+static struct Window *sMultistepLoadFont_Window;
+static u16 sMultistepLoadFont_StartOffset;
+static u16 sMultistepLoadFont_Index;
+static struct Window sTempWindow;
+static u8 sWaitType;
+static u8 sLineLength;
+static struct GlyphBuffer sGlyphBuffer;
+
+EWRAM_DATA u16 gBGTilemapBuffers[4][0x400] = {0};
+
+EWRAM_DATA u8 gStringVar1[0x100] = {0};
+EWRAM_DATA u8 gStringVar2[0x100] = {0};
+EWRAM_DATA u8 gStringVar3[0x100] = {0};
+EWRAM_DATA u8 gStringVar4[0x100] = {0};
+
+extern u16 gBattleTypeFlags;
+extern u8 gIsLinkContest;
+extern u8 gTileBuffer[];
+
+vu16 *const gBGControlRegs[] =
+{
+ &REG_BG0CNT,
+ &REG_BG1CNT,
+ &REG_BG2CNT,
+ &REG_BG3CNT,
+};
+
+vu16 *const gBGHOffsetRegs[] =
+{
+ &REG_BG0HOFS,
+ &REG_BG1HOFS,
+ &REG_BG2HOFS,
+ &REG_BG3HOFS,
+};
+
+vu16 *const gBGVOffsetRegs[] =
+{
+ &REG_BG0VOFS,
+ &REG_BG1VOFS,
+ &REG_BG2VOFS,
+ &REG_BG3VOFS,
+};
+
+const u16 gUnknown_081E29D8[] = { 0x100, 0x200, 0x400, 0x800 };
+const u16 gUnknown_081E29E0[] = { 0x100, 0x200, 0x400, 0x800 };
+const u16 gUnknown_081E29E8[] = { 1, 2, 4, 8 };
+
+static const u8 sFont0LatinGlyphs[] = INCBIN_U8("graphics/fonts/font0_lat.1bpp");
+static const u8 sFont1LatinGlyphs[] = INCBIN_U8("graphics/fonts/font1_lat.1bpp");
+static const u8 sFont0JapaneseGlyphs[] = INCBIN_U8("graphics/fonts/font0_jpn.1bpp");
+static const u8 sFont1JapaneseGlyphs[] = INCBIN_U8("graphics/fonts/font1_jpn.1bpp");
+static const u8 sBrailleGlyphs[] = INCBIN_U8("graphics/fonts/font6_braille.1bpp");
+static const u32 sDownArrowTiles[] = INCBIN_U32("graphics/fonts/down_arrow.4bpp");
+
+// clang-format off
+#include "../data/text/type1_map.h"
+#include "../data/text/type3_map.h"
+#include "../data/text/font1_widths.h"
+#include "../data/text/font4_widths.h"
+#include "../data/text/font0_widths.h"
+#include "../data/text/font3_widths.h"
+// clang-format on
+
+const u16 gUnknownPalette_81E6692[] = INCBIN_U16("graphics/fonts/unknown_81E6692.gbapal");
+const u16 gFontDefaultPalette[] = INCBIN_U16("graphics/fonts/default.gbapal");
+
+const u8 sBlankTile[8] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+
+static const u32 sGlyphMasks[9][8][3] =
+{
+ {
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0xFFFFFFFF,0xFFFFFFFF,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0xFFFFFFF0, },
+ { 0x0000000F,0xFFFFFFFF,0xFFFFFF00, },
+ { 0x000000FF,0xFFFFFFFF,0xFFFFF000, },
+ { 0x00000FFF,0xFFFFFFFF,0xFFFF0000, },
+ { 0x0000FFFF,0xFFFFFFFF,0xFFF00000, },
+ { 0x000FFFFF,0xFFFFFFFF,0xFF000000, },
+ { 0x00FFFFFF,0xFFFFFFFF,0xF0000000, },
+ { 0x0FFFFFFF,0xFFFFFFFF,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0xFFFFFF00, },
+ { 0x0000000F,0xFFFFFFFF,0xFFFFF000, },
+ { 0x000000FF,0xFFFFFFFF,0xFFFF0000, },
+ { 0x00000FFF,0xFFFFFFFF,0xFFF00000, },
+ { 0x0000FFFF,0xFFFFFFFF,0xFF000000, },
+ { 0x000FFFFF,0xFFFFFFFF,0xF0000000, },
+ { 0x00FFFFFF,0xFFFFFFFF,0x00000000, },
+ { 0x0FFFFFFF,0xFFFFFFF0,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0xFFFFF000, },
+ { 0x0000000F,0xFFFFFFFF,0xFFFF0000, },
+ { 0x000000FF,0xFFFFFFFF,0xFFF00000, },
+ { 0x00000FFF,0xFFFFFFFF,0xFF000000, },
+ { 0x0000FFFF,0xFFFFFFFF,0xF0000000, },
+ { 0x000FFFFF,0xFFFFFFFF,0x00000000, },
+ { 0x00FFFFFF,0xFFFFFFF0,0x00000000, },
+ { 0x0FFFFFFF,0xFFFFFF00,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0xFFFF0000, },
+ { 0x0000000F,0xFFFFFFFF,0xFFF00000, },
+ { 0x000000FF,0xFFFFFFFF,0xFF000000, },
+ { 0x00000FFF,0xFFFFFFFF,0xF0000000, },
+ { 0x0000FFFF,0xFFFFFFFF,0x00000000, },
+ { 0x000FFFFF,0xFFFFFFF0,0x00000000, },
+ { 0x00FFFFFF,0xFFFFFF00,0x00000000, },
+ { 0x0FFFFFFF,0xFFFFF000,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0xFFF00000, },
+ { 0x0000000F,0xFFFFFFFF,0xFF000000, },
+ { 0x000000FF,0xFFFFFFFF,0xF0000000, },
+ { 0x00000FFF,0xFFFFFFFF,0x00000000, },
+ { 0x0000FFFF,0xFFFFFFF0,0x00000000, },
+ { 0x000FFFFF,0xFFFFFF00,0x00000000, },
+ { 0x00FFFFFF,0xFFFFF000,0x00000000, },
+ { 0x0FFFFFFF,0xFFFF0000,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0xFF000000, },
+ { 0x0000000F,0xFFFFFFFF,0xF0000000, },
+ { 0x000000FF,0xFFFFFFFF,0x00000000, },
+ { 0x00000FFF,0xFFFFFFF0,0x00000000, },
+ { 0x0000FFFF,0xFFFFFF00,0x00000000, },
+ { 0x000FFFFF,0xFFFFF000,0x00000000, },
+ { 0x00FFFFFF,0xFFFF0000,0x00000000, },
+ { 0x0FFFFFFF,0xFFF00000,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0xF0000000, },
+ { 0x0000000F,0xFFFFFFFF,0x00000000, },
+ { 0x000000FF,0xFFFFFFF0,0x00000000, },
+ { 0x00000FFF,0xFFFFFF00,0x00000000, },
+ { 0x0000FFFF,0xFFFFF000,0x00000000, },
+ { 0x000FFFFF,0xFFFF0000,0x00000000, },
+ { 0x00FFFFFF,0xFFF00000,0x00000000, },
+ { 0x0FFFFFFF,0xFF000000,0x00000000, },
+ },
+ {
+ { 0x00000000,0xFFFFFFFF,0x00000000, },
+ { 0x0000000F,0xFFFFFFF0,0x00000000, },
+ { 0x000000FF,0xFFFFFF00,0x00000000, },
+ { 0x00000FFF,0xFFFFF000,0x00000000, },
+ { 0x0000FFFF,0xFFFF0000,0x00000000, },
+ { 0x000FFFFF,0xFFF00000,0x00000000, },
+ { 0x00FFFFFF,0xFF000000,0x00000000, },
+ { 0x0FFFFFFF,0xF0000000,0x00000000, },
+ },
+};
+
+static const struct ShiftAmount sGlyphShiftAmounts[8] =
+{
+ { 0, 32 },
+ { 4, 28 },
+ { 8, 24 },
+ { 12, 20 },
+ { 16, 16 },
+ { 20, 12 },
+ { 24, 8 },
+ { 28, 4 },
+};
+
+typedef void (*PrintGlyphFunc)(struct Window *, u32);
+
+static const PrintGlyphFunc sPrintGlyphFuncs[] =
+{
+ PrintGlyph_TextMode0,
+ PrintGlyph_TextMode1,
+ PrintGlyph_TextMode2,
+};
+
+typedef void (*WriteGlyphTilemapFunc)(struct Window *, u32);
+
+static const WriteGlyphTilemapFunc sWriteGlyphTilemapFuncs[] =
+{
+ WriteGlyphTilemap_Font0_Font3,
+ WriteGlyphTilemap_Font1_Font4,
+ WriteGlyphTilemap_Font2_Font5,
+ WriteGlyphTilemap_Font0_Font3,
+ WriteGlyphTilemap_Font1_Font4,
+ WriteGlyphTilemap_Font2_Font5,
+ WriteGlyphTilemap_Font6,
+};
+
+static const struct Window sDefaultWindow = { .language = GAME_LANGUAGE };
+
+typedef u8 (*ExtCtrlCodeFunc)(struct Window *);
+
+static const ExtCtrlCodeFunc sExtCtrlCodeFuncs[] =
+{
+ ExtCtrlCode_Nop,
+ ExtCtrlCode_ForegroundColor,
+ ExtCtrlCode_BackgroundColor,
+ ExtCtrlCode_ShadowColor,
+ ExtCtrlCode_AllColors,
+ ExtCtrlCode_Palette,
+ ExtCtrlCode_Font,
+ ExtCtrlCode_DefaultFont,
+ ExtCtrlCode_Pause,
+ ExtCtrlCode_WaitButton,
+ ExtCtrlCode_WaitSound,
+ ExtCtrlCode_PlayBGM,
+ ExtCtrlCode_Escape,
+ ExtCtrlCode_Nop2,
+ ExtCtrlCode_SetCursorY,
+ ExtCtrlCode_ClearWindowTextLines,
+ ExtCtrlCode_PlaySE,
+ ExtCtrlCode_Skip,
+ ExtCtrlCode_SetCursorX,
+ ExtCtrlCode_SkipTo,
+ ExtCtrlCode_Spacing,
+ ExtCtrlCode_Japanese,
+ ExtCtrlCode_Latin,
+};
+
+extern const u32 gFont3LatinGlyphs[];
+extern const u32 gFont4LatinGlyphs[];
+extern const u32 gFont3JapaneseGlyphs[];
+extern const u32 gFont4JapaneseGlyphs[];
+
+static const struct Font sFonts[] =
+{
+ // Japanese fonts
+ { 0, (u8 *)sFont0JapaneseGlyphs, 16, 8 },
+ { 1, (u8 *)sFont1JapaneseGlyphs, 8, 0 },
+ { 2, (u8 *)sFont1JapaneseGlyphs, 8, 0 },
+ { 4, (u8 *)gFont3JapaneseGlyphs, 64, 512 },
+ { 1, (u8 *)gFont4JapaneseGlyphs, 32, 0 },
+ { 2, (u8 *)gFont4JapaneseGlyphs, 32, 0 },
+ { 3, (u8 *)sBrailleGlyphs, 8, 0 },
+ // Latin
+ { 0, (u8 *)sFont0LatinGlyphs, 16, 8 },
+ { 1, (u8 *)sFont1LatinGlyphs, 8, 0 },
+ { 2, (u8 *)sFont1LatinGlyphs, 8, 0 },
+ { 0, (u8 *)gFont3LatinGlyphs, 64, 32 },
+ { 1, (u8 *)gFont4LatinGlyphs, 32, 0 },
+ { 2, (u8 *)gFont4LatinGlyphs, 32, 0 },
+ { 3, (u8 *)sBrailleGlyphs, 8, 0 },
+};
+
+static const u8 sTextSpeedDelays[] = { 6, 3, 1 }; // slow, mid, fast
+
+static const u8 sExtCtrlCodeLengths[] =
+{
+ 1,
+ 2,
+ 2,
+ 2,
+ 4,
+ 2,
+ 2,
+ 1,
+ 2,
+ 1,
+ 1,
+ 3,
+ 2,
+ 2,
+ 2,
+ 1,
+ 3,
+ 2,
+ 2,
+ 2,
+ 2,
+ 1,
+ 1,
+};
+
+typedef void (*ShiftGlyphTileUnshadowedFunc)(struct GlyphBuffer *, u8 *, u32 *, u8);
+
+static const ShiftGlyphTileUnshadowedFunc sShiftGlyphTileUnshadowedFuncs[] =
+{
+ ShiftGlyphTile_UnshadowedFont_Width0,
+ ShiftGlyphTile_UnshadowedFont_Width1,
+ ShiftGlyphTile_UnshadowedFont_Width2,
+ ShiftGlyphTile_UnshadowedFont_Width3,
+ ShiftGlyphTile_UnshadowedFont_Width4,
+ ShiftGlyphTile_UnshadowedFont_Width5,
+ ShiftGlyphTile_UnshadowedFont_Width6,
+ ShiftGlyphTile_UnshadowedFont_Width7,
+ ShiftGlyphTile_UnshadowedFont_Width8,
+};
+
+typedef void (*ShiftGlyphTileShadowedFunc)(struct GlyphBuffer *, u32 *, u32 *, u8);
+
+static const ShiftGlyphTileShadowedFunc sShiftGlyphTileShadowedFuncs[] =
+{
+ ShiftGlyphTile_ShadowedFont_Width0,
+ ShiftGlyphTile_ShadowedFont_Width1,
+ ShiftGlyphTile_ShadowedFont_Width2,
+ ShiftGlyphTile_ShadowedFont_Width3,
+ ShiftGlyphTile_ShadowedFont_Width4,
+ ShiftGlyphTile_ShadowedFont_Width5,
+ ShiftGlyphTile_ShadowedFont_Width6,
+ ShiftGlyphTile_ShadowedFont_Width7,
+ ShiftGlyphTile_ShadowedFont_Width8,
+};
+
+const struct WindowConfig gWindowConfig_81E6C3C =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 0, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6C58 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 24, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 26, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(24), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6C74 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 0, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 1, // foreground color
+ 0, // background color
+ 3, // shadow color
+ 4, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)OBJ_VRAM0, // tile data
+ NULL, // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6C90 =
+{
+ 0, // BG number
+ 1, // BG character base block
+ 30, // BG screen base block
+ 2, // BG priority
+ 31, // palette number
+ 15, // foreground color
+ 0, // background color
+ 1, // shadow color
+ 4, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(1), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6CAC =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 0, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 15, // foreground color
+ 0, // background color
+ 1, // shadow color
+ 4, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 8, // width
+ 60, // height
+ gTileBuffer, // tile data
+ NULL, // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6CC8 =
+{
+ 2, // BG number
+ 2, // BG character base block
+ 15, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(15), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6CE4 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6D00 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 2, // foreground color
+ 15, // background color
+ 3, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6D1C =
+{
+ 1, // BG number
+ 0, // BG character base block
+ 31, // BG screen base block
+ 1, // BG priority
+ 15, // palette number
+ 2, // foreground color
+ 15, // background color
+ 3, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6D38 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 0, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 15, // foreground color
+ 0, // background color
+ 14, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 8, // width
+ 64, // height
+ gTileBuffer, // tile data
+ NULL, // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6D54 =
+{
+ 3, // BG number
+ 3, // BG character base block
+ 15, // BG screen base block
+ 3, // BG priority
+ 2, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(3), // tile data
+ (u16 *)BG_SCREEN_ADDR(15), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6D70 =
+{
+ 3, // BG number
+ 3, // BG character base block
+ 15, // BG screen base block
+ 3, // BG priority
+ 3, // palette number
+ 1, // foreground color
+ 3, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(3), // tile data
+ (u16 *)BG_SCREEN_ADDR(15), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6D8C =
+{
+ 1, // BG number
+ 0, // BG character base block
+ 14, // BG screen base block
+ 1, // BG priority
+ 0, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(14), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6DA8 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 12, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(11), // tilemap
+};
+
+const struct WindowConfig WindowConfig_TrainerCard_Back_Values =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 30, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig WindowConfig_TrainerCard_Back_Labels =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 30, // BG screen base block
+ 0, // BG priority
+ 14, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6DFC =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6E18 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 31, // BG screen base block
+ 1, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6E34 =
+{
+ 1, // BG number
+ 0, // BG character base block
+ 31, // BG screen base block
+ 1, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6E50 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 28, // BG screen base block
+ 0, // BG priority
+ 13, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(28), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6E6C =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 30, // BG screen base block
+ 0, // BG priority
+ 13, // palette number
+ 15, // foreground color
+ 0, // background color
+ 10, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6E88 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6EA4 =
+{
+ 1, // BG number
+ 0, // BG character base block
+ 28, // BG screen base block
+ 1, // BG priority
+ 1, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 8, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(28), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6EC0 =
+{
+ 2, // BG number
+ 2, // BG character base block
+ 29, // BG screen base block
+ 2, // BG priority
+ 1, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 8, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(29), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6EDC =
+{
+ 1, // BG number
+ 0, // BG character base block
+ 28, // BG screen base block
+ 1, // BG priority
+ 2, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 8, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(28), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6EF8 =
+{
+ 2, // BG number
+ 2, // BG character base block
+ 29, // BG screen base block
+ 2, // BG priority
+ 2, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 8, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(29), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6F14 =
+{
+ 1, // BG number
+ 0, // BG character base block
+ 28, // BG screen base block
+ 1, // BG priority
+ 3, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 8, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(28), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6F30 =
+{
+ 2, // BG number
+ 2, // BG character base block
+ 29, // BG screen base block
+ 2, // BG priority
+ 3, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 8, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(29), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6F4C =
+{
+ 3, // BG number
+ 0, // BG character base block
+ 30, // BG screen base block
+ 3, // BG priority
+ 0, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6F68 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 13, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(13), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6F84 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 15, // foreground color
+ 0, // background color
+ 1, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6FA0 =
+{
+ 1, // BG number
+ 0, // BG character base block
+ 24, // BG screen base block
+ 3, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(24), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6FBC =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 30, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 15, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6FD8 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 24, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 15, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(24), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E6FF4 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 24, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(24), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7010 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 30, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E702C =
+{
+ 3, // BG number
+ 2, // BG character base block
+ 15, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(15), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7048 =
+{
+ 2, // BG number
+ 2, // BG character base block
+ 14, // BG screen base block
+ 2, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 16, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 16, // width
+ 32, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(14), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7064 =
+{
+ 2, // BG number
+ 2, // BG character base block
+ 14, // BG screen base block
+ 2, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(14), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7080 =
+{
+ 3, // BG number
+ 0, // BG character base block
+ 30, // BG screen base block
+ 3, // BG priority
+ 11, // palette number
+ 1, // foreground color
+ 15, // background color
+ 5, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E709C =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 31, // BG screen base block
+ 1, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E70B8 =
+{
+ 2, // BG number
+ 0, // BG character base block
+ 30, // BG screen base block
+ 2, // BG priority
+ 11, // palette number
+ 1, // foreground color
+ 0, // background color
+ 5, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E70D4 =
+{
+ 3, // BG number
+ 0, // BG character base block
+ 30, // BG screen base block
+ 3, // BG priority
+ 11, // palette number
+ 1, // foreground color
+ 15, // background color
+ 5, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E70F0 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 0, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 15, // foreground color
+ 1, // background color
+ 14, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 32, // width
+ 32, // height
+ gTileBuffer, // tile data
+ NULL, // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E710C =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 31, // BG screen base block
+ 1, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7128 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7144 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 13, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7160 =
+{
+ 1, // BG number
+ 1, // BG character base block
+ 10, // BG screen base block
+ 1, // BG priority
+ 14, // palette number
+ 1, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(1), // tile data
+ (u16 *)BG_SCREEN_ADDR(10), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E717C =
+{
+ 0, // BG number
+ 3, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 15, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(3), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7198 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 15, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 15, // foreground color
+ 0, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(15), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E71B4 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 15, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(15), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E71D0 =
+{
+ 1, // BG number
+ 1, // BG character base block
+ 28, // BG screen base block
+ 0, // BG priority
+ 5, // palette number
+ 13, // foreground color
+ 14, // background color
+ 15, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(1), // tile data
+ (u16 *)BG_SCREEN_ADDR(28), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E71EC =
+{
+ 2, // BG number
+ 1, // BG character base block
+ 30, // BG screen base block
+ 0, // BG priority
+ 5, // palette number
+ 13, // foreground color
+ 14, // background color
+ 15, // shadow color
+ 3, // font
+ 0, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(1), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7208 =
+{
+ 0, // BG number
+ 2, // BG character base block
+ 28, // BG screen base block
+ 0, // BG priority
+ 8, // palette number
+ 1, // foreground color
+ 0, // background color
+ 2, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(28), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7224 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 31, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(0), // tile data
+ (u16 *)BG_SCREEN_ADDR(31), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7240 =
+{
+ 1, // BG number
+ 2, // BG character base block
+ 30, // BG screen base block
+ 0, // BG priority
+ 15, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)BG_CHAR_ADDR(2), // tile data
+ (u16 *)BG_SCREEN_ADDR(30), // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E725C =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 0, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 15, // foreground color
+ 0, // background color
+ 14, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 30, // width
+ 20, // height
+ (u8 *)OBJ_VRAM0, // tile data
+ NULL, // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7278 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 0, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 3, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 16, // width
+ 32, // height
+ gTileBuffer, // tile data
+ NULL, // tilemap
+};
+
+const struct WindowConfig gWindowConfig_81E7294 =
+{
+ 0, // BG number
+ 0, // BG character base block
+ 0, // BG screen base block
+ 0, // BG priority
+ 0, // palette number
+ 1, // foreground color
+ 15, // background color
+ 8, // shadow color
+ 4, // font
+ 2, // text mode
+ 0, // spacing
+ 0, // tilemap left coordinate
+ 0, // tilemap top coordinate
+ 16, // width
+ 32, // height
+ gTileBuffer, // tile data
+ NULL, // tilemap
+};
+
+static void UpdateBGRegs(const struct WindowConfig *winConfig)
+{
+ u8 bgNum = winConfig->bgNum;
+ *gBGHOffsetRegs[bgNum] = 0;
+ *gBGVOffsetRegs[bgNum] = 0;
+ *gBGControlRegs[bgNum] = winConfig->priority | (winConfig->screenBaseBlock << 8) | (winConfig->charBaseBlock << 2);
+}
+
+static void ClearBGMem(const struct WindowConfig *winConfig)
+{
+ CpuFastFill(0, winConfig->tileData, 32);
+
+ if (winConfig->tilemap)
+ CpuFastFill(0, winConfig->tilemap, 0x800);
+}
+
+void LoadFontDefaultPalette(const struct WindowConfig *winConfig)
+{
+ LoadPalette(gFontDefaultPalette, 16 * winConfig->paletteNum, 32);
+}
+
+void SetUpWindowConfig(const struct WindowConfig *winConfig)
+{
+ UpdateBGRegs(winConfig);
+ ClearBGMem(winConfig);
+ LoadFontDefaultPalette(winConfig);
+}
+
+u16 InitWindowTileData(struct Window *win, u16 startOffset)
+{
+ u16 retVal;
+
+ win->tileDataStartOffset = startOffset;
+ retVal = 0;
+
+ switch (win->config->textMode)
+ {
+ case 2:
+ retVal = InitVariableWidthFontTileData(win, startOffset);
+ break;
+ case 1:
+ switch (win->config->fontNum)
+ {
+ case 0:
+ case 3:
+ retVal = LoadFixedWidthFont(win, startOffset);
+ break;
+ case 1:
+ case 2:
+ retVal = LoadFixedWidthFont_Font1Latin(win, startOffset);
+ break;
+ case 4:
+ case 5:
+ retVal = LoadFixedWidthFont_Font4Latin(win, startOffset);
+ break;
+ case 6:
+ retVal = LoadFixedWidthFont_Braille(win, startOffset);
+ break;
+ }
+ break;
+ }
+
+ return retVal;
+}
+
+static u16 InitVariableWidthFontTileData(struct Window *win, u16 startOffset)
+{
+ u8 *buffer;
+
+ win->tileDataStartOffset = startOffset;
+ win->tileDataOffset = 2;
+ buffer = win->tileData + 32 * win->tileDataStartOffset;
+ CpuFastFill(0, buffer, 32);
+ ApplyColors_UnshadowedFont(sBlankTile, (u32 *)(buffer + 32), win->config->foregroundColor, win->config->backgroundColor);
+ return win->tileDataStartOffset + win->tileDataOffset + win->width * win->height;
+}
+
+static u16 LoadFixedWidthFont(struct Window *win, u16 startOffset)
+{
+ s32 glyph;
+ u8 *buffer = win->tileData + 32 * startOffset;
+ for (glyph = 0; glyph < 256; glyph++)
+ {
+ LoadFixedWidthGlyph(win, glyph, buffer);
+ buffer += 64;
+ }
+ return 2 * glyph;
+}
+
+static u16 LoadFixedWidthFont_Font1Latin(struct Window *win, u16 startOffset)
+{
+ s32 i;
+ u8 *buffer = win->tileData + 32 * startOffset;
+ for (i = 0; i < 256; i++)
+ {
+ ApplyColors_UnshadowedFont(&sFont1LatinGlyphs[8 * i], (u32 *)buffer, win->foregroundColor, win->backgroundColor);
+ buffer += 32;
+ }
+ return i;
+}
+
+static u16 LoadFixedWidthFont_Font4Latin(struct Window *win, u16 startOffset)
+{
+ s32 i;
+ u8 *buffer = win->tileData + 32 * startOffset;
+ for (i = 0; i < 256; i++)
+ {
+ ApplyColors_ShadowedFont(&gFont4LatinGlyphs[8 * i], buffer, win->foregroundColor, win->shadowColor, win->backgroundColor);
+ buffer += 32;
+ }
+ return i;
+}
+
+static u16 LoadFixedWidthFont_Braille(struct Window *win, u16 startOffset)
+{
+ s32 i;
+ u8 *buffer = win->tileData + 32 * startOffset;
+ for (i = 0; i < 256; i++)
+ {
+ ApplyColors_UnshadowedFont(&sBrailleGlyphs[8 * i], (u32 *)buffer, win->foregroundColor, win->backgroundColor);
+ buffer += 32;
+ }
+ return i;
+}
+
+u32 MultistepInitWindowTileData(struct Window *win, u16 startOffset)
+{
+ u32 retVal;
+ sMultistepLoadFont_Window = win;
+ sMultistepLoadFont_Index = 0;
+ sMultistepLoadFont_StartOffset = startOffset;
+ win->tileDataStartOffset = startOffset;
+ retVal = 0;
+
+ switch (win->config->textMode)
+ {
+ case 2:
+ retVal = InitVariableWidthFontTileData(win, startOffset);
+ break;
+ case 1:
+ retVal = 256;
+ if (win->config->fontNum == 0
+ || win->config->fontNum == 3)
+ retVal *= 2;
+ break;
+ }
+
+ return retVal;
+}
+
+bool32 MultistepLoadFont(void)
+{
+ bool32 retVal = TRUE;
+
+ if (sMultistepLoadFont_Window->config->textMode == 1)
+ {
+ s32 i;
+
+ for (i = sMultistepLoadFont_Index; i < sMultistepLoadFont_Index + 16; i++)
+ MultistepLoadFont_LoadGlyph(sMultistepLoadFont_Window, sMultistepLoadFont_StartOffset, i);
+
+ sMultistepLoadFont_Index += 16;
+
+ if (sMultistepLoadFont_Index < 256)
+ retVal = FALSE;
+ }
+
+ return retVal;
+}
+
+static void MultistepLoadFont_LoadGlyph(struct Window *win, u16 startOffset, u8 glyph)
+{
+ u8 *buffer;
+
+ switch (win->config->fontNum)
+ {
+ case 0:
+ case 3:
+ buffer = win->tileData + 32 * startOffset + 64 * glyph;
+ LoadFixedWidthGlyph(win, glyph, buffer);
+ break;
+ case 1:
+ case 2:
+ buffer = win->tileData + 32 * (glyph + startOffset);
+ ApplyColors_UnshadowedFont(
+ &sFont1LatinGlyphs[8 * glyph],
+ (u32 *)buffer,
+ win->foregroundColor,
+ win->backgroundColor);
+ break;
+ case 4:
+ case 5:
+ buffer = win->tileData + 32 * (glyph + startOffset);
+ ApplyColors_ShadowedFont(
+ &gFont4LatinGlyphs[8 * glyph],
+ buffer,
+ win->foregroundColor,
+ win->shadowColor,
+ win->backgroundColor);
+ break;
+ }
+}
+
+void EmptyFunc(void)
+{
+}
+
+void InitWindowFromConfig(struct Window *win, const struct WindowConfig *winConfig)
+{
+ *win = sDefaultWindow;
+ win->config = (struct WindowConfig *)winConfig;
+ win->textMode = winConfig->textMode;
+ win->spacing = winConfig->spacing;
+ win->fontNum = winConfig->fontNum;
+ win->paletteNum = winConfig->paletteNum;
+ win->tilemapLeft = winConfig->tilemapLeft;
+ win->tilemapTop = winConfig->tilemapTop;
+ win->width = winConfig->width;
+ win->height = winConfig->height;
+ win->tileData = winConfig->tileData;
+ win->tilemap = winConfig->tilemap;
+ InitColors(win);
+ SetBackgroundColor(win, winConfig->backgroundColor);
+ SetShadowColor(win, winConfig->shadowColor);
+ SetForegroundColor(win, winConfig->foregroundColor);
+}
+
+void InitWindow(struct Window *win, const u8 *text, u16 tileDataStartOffset, u8 left, u8 top)
+{
+ struct WindowConfig *winConfig = win->config;
+ win->textMode = winConfig->textMode;
+ win->fontNum = winConfig->fontNum;
+ win->language = GAME_LANGUAGE;
+ win->paletteNum = winConfig->paletteNum;
+ win->win_field_B = 0;
+ win->win_field_C = 0;
+ win->delayCounter = 0;
+ win->spacing = winConfig->spacing;
+ win->win_field_F = 0;
+ win->tilemapLeft = winConfig->tilemapLeft;
+ win->tilemapTop = winConfig->tilemapTop;
+ win->width = winConfig->width;
+ win->height = winConfig->height;
+ win->text = text;
+ win->textIndex = 0;
+ win->tileDataStartOffset = tileDataStartOffset;
+ win->tileDataOffset = 0;
+ win->left = 8 * left;
+ win->cursorX = 0;
+ win->top = 8 * top;
+ win->cursorY = 0;
+ win->state = WIN_STATE_BEGIN;
+ win->downArrowCounter = 0;
+ win->tileData = winConfig->tileData;
+ win->tilemap = winConfig->tilemap;
+ InitColors(win);
+ SetBackgroundColor(win, winConfig->backgroundColor);
+ SetShadowColor(win, winConfig->shadowColor);
+ SetForegroundColor(win, winConfig->foregroundColor);
+}
+
+void sub_8002E4C(struct Window *win, const u8 *text, u16 tileDataStartOffset, u8 left, u16 top, u32 a6)
+{
+ u8 val;
+
+ InitWindow(win, text, tileDataStartOffset, 0, 0);
+ win->left = left;
+ win->top = top;
+ val = 0;
+ if (a6)
+ val = 255;
+ win->win_field_F = val;
+ if (val)
+ ClipLeft(win);
+}
+
+void sub_8002E90(struct Window *win, const u8 *text)
+{
+ win->state = WIN_STATE_NORMAL;
+ win->text = text;
+ win->textIndex = 0;
+ win->downArrowCounter = 0;
+ win->win_field_B = -1;
+ win->win_field_C = 0;
+ win->delayCounter = 0;
+}
+
+void sub_8002EB0(struct Window *win, const u8 *text, u16 tileDataStartOffset, u8 left, u8 top)
+{
+ gMain.watchedKeysMask = A_BUTTON | B_BUTTON;
+ gMain.watchedKeysPressed = 0;
+ sWaitType = 0;
+ sLineLength = 26;
+ InitWindow(win, text, tileDataStartOffset, left, top);
+ win->win_field_B = -1;
+ if (win->textMode == 0)
+ {
+ u16 val = GetCursorTileNum(win, 0, 0);
+ u8 *buffer = win->tileData + 32 * val;
+ ApplyColors_UnshadowedFont(sBlankTile, (u32 *)buffer, win->backgroundColor, win->backgroundColor);
+ ApplyColors_UnshadowedFont(&sFont1LatinGlyphs[8 * 0x6E], (u32 *)(buffer + 32), win->foregroundColor, win->backgroundColor);
+ win->tileDataOffset = 2;
+ }
+}
+
+u8 sub_8002F44(struct Window *win)
+{
+ while (win->state)
+ {
+ if (win->state == WIN_STATE_NEWLINE)
+ {
+ AddToCursorY(win, 16);
+ win->cursorX = 0;
+ if (win->win_field_F)
+ ClipLeft(win);
+ win->state = WIN_STATE_NORMAL;
+ }
+ else if (win->state == WIN_STATE_PLACEHOLDER)
+ {
+ sub_8002FA0(win, GetExpandedPlaceholder(win->text[win->textIndex++]));
+ }
+
+ InterpretText(win);
+ }
+ return 1;
+}
+
+static u8 sub_8002FA0(struct Window *win, const u8 *text)
+{
+ u8 retVal;
+ u8 savedLanguage = win->language;
+ const u8 *savedText = win->text;
+ u16 savedTextIndex = win->textIndex;
+ win->text = text;
+ win->textIndex = 0;
+ win->state = WIN_STATE_NORMAL;
+ retVal = sub_8002F44(win);
+ win->text = savedText;
+ win->textIndex = savedTextIndex;
+ win->state = WIN_STATE_NORMAL;
+ win->language = savedLanguage;
+ return retVal;
+}
+
+static u8 InterpretText(struct Window *win)
+{
+ u8 c = win->text[win->textIndex++];
+
+ switch (c)
+ {
+ case 0xFF:
+ ClipRight(win);
+ win->state = WIN_STATE_END;
+ return 0;
+ case 0xFD:
+ win->state = WIN_STATE_PLACEHOLDER;
+ return 2;
+ case 0xFE:
+ ClipRight(win);
+ win->state = WIN_STATE_NEWLINE;
+ return 2;
+ case 0xFB:
+ DrawInitialDownArrow(win);
+ win->state = WIN_STATE_PARAGRAPH;
+ return 2;
+ case 0xFA:
+ DrawInitialDownArrow(win);
+ win->state = WIN_STATE_NEWLINE_WAIT;
+ return 2;
+ case 0xFC:
+ return HandleExtCtrlCode(win);
+ }
+
+ sPrintGlyphFuncs[win->textMode](win, c);
+ return 1;
+}
+
+static u8 HandleExtCtrlCode(struct Window *win)
+{
+ return sExtCtrlCodeFuncs[win->text[win->textIndex++]](win);
+}
+
+static u8 ExtCtrlCode_Nop(struct Window *win)
+{
+ return 2;
+}
+
+static u8 ExtCtrlCode_ForegroundColor(struct Window *win)
+{
+ SetForegroundColor(win, win->text[win->textIndex++]);
+ return 2;
+}
+
+static u8 ExtCtrlCode_BackgroundColor(struct Window *win)
+{
+ SetBackgroundColor(win, win->text[win->textIndex++]);
+ return 2;
+}
+
+static u8 ExtCtrlCode_ShadowColor(struct Window *win)
+{
+ SetShadowColor(win, win->text[win->textIndex++]);
+ return 2;
+}
+
+static u8 ExtCtrlCode_AllColors(struct Window *win)
+{
+ SetForegroundColor(win, win->text[win->textIndex++]);
+ SetBackgroundColor(win, win->text[win->textIndex++]);
+ SetShadowColor(win, win->text[win->textIndex++]);
+ return 2;
+}
+
+static u8 ExtCtrlCode_Palette(struct Window *win)
+{
+ win->paletteNum = win->text[win->textIndex++];
+ return 2;
+}
+
+static u8 ExtCtrlCode_Font(struct Window *win)
+{
+ win->fontNum = win->text[win->textIndex++];
+ return 2;
+}
+
+static u8 ExtCtrlCode_DefaultFont(struct Window *win)
+{
+ win->fontNum = win->config->fontNum;
+ return 2;
+}
+
+static u8 ExtCtrlCode_Pause(struct Window *win)
+{
+ ClipRight(win);
+ win->state = WIN_STATE_PAUSE;
+ win->delayCounter = win->text[win->textIndex++];
+ return 2;
+}
+
+static u8 ExtCtrlCode_WaitButton(struct Window *win)
+{
+ ClipRight(win);
+ win->state = WIN_STATE_WAIT_BUTTON;
+ return 2;
+}
+
+static u8 ExtCtrlCode_WaitSound(struct Window *win)
+{
+ ClipRight(win);
+ win->state = WIN_STATE_WAIT_SOUND;
+ return 2;
+}
+
+static u8 ExtCtrlCode_PlayBGM(struct Window *win)
+{
+ u16 loByte = win->text[win->textIndex++];
+ u16 hiByte = win->text[win->textIndex++] << 8;
+ PlayBGM(loByte | hiByte);
+ return 2;
+}
+
+static u8 ExtCtrlCode_Escape(struct Window *win)
+{
+ sPrintGlyphFuncs[win->textMode](win, win->text[win->textIndex++]);
+ return 1;
+}
+
+u8 ExtCtrlCode_Nop2(struct Window *win)
+{
+ return 1;
+}
+
+static u8 ExtCtrlCode_SetCursorY(struct Window *win)
+{
+ ClipRight(win);
+ AddToCursorY(win, 8 * win->text[win->textIndex++]);
+ return 1;
+}
+
+static u8 ExtCtrlCode_ClearWindowTextLines(struct Window *win)
+{
+ ClearWindowTextLines(win);
+ return 2;
+}
+
+static u8 ExtCtrlCode_PlaySE(struct Window *win)
+{
+ u16 loByte = win->text[win->textIndex++];
+ u16 hiByte = win->text[win->textIndex++] << 8;
+ PlaySE(loByte | hiByte);
+ return 2;
+}
+
+static void DrawSpace(struct Window *win)
+{
+ if (win->textMode == 1 || (win->left + win->cursorX) & 7 || win->spacing <= 7)
+ {
+ sPrintGlyphFuncs[win->textMode](win, 0);
+ }
+ else
+ {
+ u32 val = sGlyphBuffer.background;
+ u16 index = GetCursorTileNum(win, 0, 0);
+ u32 *buffer = (u32 *)(win->tileData + 32 * index);
+ buffer[0] = val;
+ buffer[1] = val;
+ buffer[2] = val;
+ buffer[3] = val;
+ buffer[4] = val;
+ buffer[5] = val;
+ buffer[6] = val;
+ buffer[7] = val;
+ index = GetCursorTileNum(win, 0, 1);
+ buffer = (u32 *)(win->tileData + 32 * index);
+ buffer[0] = val;
+ buffer[1] = val;
+ buffer[2] = val;
+ buffer[3] = val;
+ buffer[4] = val;
+ buffer[5] = val;
+ buffer[6] = val;
+ buffer[7] = val;
+ UpdateTilemap(win, 1);
+ AddToCursorX(win, 8);
+ }
+}
+
+static void sub_8003344(struct Window *win, u8 newX)
+{
+ u8 savedSpacing = win->spacing;
+
+ if (newX - win->cursorX <= 8)
+ win->spacing = newX - win->cursorX;
+ else
+ win->spacing = 8 - ((win->left + win->cursorX) & 7);
+
+ while (win->cursorX < newX)
+ {
+ s32 spacing;
+ DrawSpace(win);
+ spacing = newX - win->cursorX;
+ if (spacing >= 8)
+ spacing = 8;
+ win->spacing = spacing;
+ }
+
+ win->spacing = savedSpacing;
+}
+
+static u8 ExtCtrlCode_Skip(struct Window *win)
+{
+ sub_8003344(win, win->cursorX + win->text[win->textIndex++]);
+ return 1;
+}
+
+static u8 ExtCtrlCode_SetCursorX(struct Window *win)
+{
+ ClipRight(win);
+ SetCursorX(win, win->text[win->textIndex++]);
+ return 1;
+}
+
+static u8 ExtCtrlCode_SkipTo(struct Window *win)
+{
+ sub_8003344(win, win->text[win->textIndex++]);
+ return 1;
+}
+
+static u8 ExtCtrlCode_Spacing(struct Window *win)
+{
+ win->spacing = win->text[win->textIndex++];
+ return 2;
+}
+
+static u8 ExtCtrlCode_Japanese(struct Window *win)
+{
+ win->language = LANGUAGE_JAPANESE;
+ return 2;
+}
+
+static u8 ExtCtrlCode_Latin(struct Window *win)
+{
+ win->language = GAME_LANGUAGE;
+ return 2;
+}
+
+u8 sub_8003418(struct Window *win)
+{
+ u8 retVal = 1;
+ while (win->state)
+ {
+ if (win->state == WIN_STATE_NEWLINE)
+ {
+ AddToCursorY(win, 16);
+ win->cursorX = 0;
+ if (win->win_field_F)
+ ClipLeft(win);
+ win->state = WIN_STATE_NORMAL;
+ }
+ if (InterpretText(win) == 1)
+ {
+ retVal = 0;
+ break;
+ }
+ }
+ return retVal;
+}
+
+u8 sub_8003460(struct Window *win, const u8 *text, u16 tileDataStartOffset, u8 left, u8 top)
+{
+ InitWindow(win, text, tileDataStartOffset, left, top);
+ return sub_8002F44(win);
+}
+
+u8 sub_8003490(struct Window *win, u8 c, u16 tileDataStartOffset, u8 left, u8 top)
+{
+ u8 retVal;
+ u8 text[2];
+ text[0] = c;
+ text[1] = EOS;
+ InitWindow(win, text, tileDataStartOffset, left, top);
+ retVal = InterpretText(win);
+ ClipRight(win);
+ return retVal;
+}
+
+void sub_80034D4(u8 *tileData, const u8 *text)
+{
+ sub_8004E3C((struct WindowConfig *)&gWindowConfig_81E6C74, tileData, text);
+}
+
+u8 sub_80034EC(u8 *str)
+{
+ return GetStringWidthGivenWindowConfig((struct WindowConfig *)&gWindowConfig_81E6C74, str);
+}
+
+u8 *sub_8003504(u8 *dest, s32 value, u8 alignAmount, u8 alignType)
+{
+ sTempWindow.config = (struct WindowConfig *)&gWindowConfig_81E6C74;
+ InitWindow(&sTempWindow, 0, 0, 0, 0);
+ return AlignInt2(&sTempWindow, dest, value, alignAmount, alignType);
+}
+
+u8 *sub_8003558(u8 *dest, const u8 *src, u8 alignAmount, u8 alignType)
+{
+ sTempWindow.config = (struct WindowConfig *)&gWindowConfig_81E6C74;
+ InitWindow(&sTempWindow, src, 0, 0, 0);
+ return AlignString(&sTempWindow, dest, src, alignAmount, alignType);
+}
+
+u8 sub_80035AC(struct Window *win)
+{
+ sWaitType = 0;
+ return UpdateWindowText(win);
+}
+
+static u8 UpdateWindowText(struct Window *win)
+{
+ switch (win->state)
+ {
+ case WIN_STATE_WAIT_BUTTON:
+ if (PlayerCanInterruptWait(win))
+ {
+ if (gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ win->delayCounter--;
+ if (win->delayCounter)
+ return 0;
+ }
+ win->state = WIN_STATE_NORMAL;
+ return 0;
+ case WIN_STATE_INTERRUPTIBLE_PAUSE:
+ if (PlayerCanInterruptWait(win) && (gMain.heldKeys & (A_BUTTON | B_BUTTON)) && gMain.watchedKeysPressed == TRUE)
+ {
+ win->delayCounter = 0;
+ win->state = WIN_STATE_NORMAL;
+ break;
+ }
+ case WIN_STATE_PAUSE:
+ if (win->delayCounter)
+ {
+ win->delayCounter--;
+ if (win->delayCounter)
+ return 0;
+ }
+
+ win->state = WIN_STATE_NORMAL;
+ break;
+ case WIN_STATE_PARAGRAPH:
+ if (!WaitWithDownArrow(win))
+ return 0;
+ ClearWindowTextLines(win);
+ win->state = WIN_STATE_NORMAL;
+ BLOCK_CROSS_JUMP
+ return 0;
+ case WIN_STATE_NEWLINE_WAIT:
+ if (!WaitWithDownArrow(win))
+ return 0;
+ ScrollWindowTextLines(win);
+ win->state = WIN_STATE_NORMAL;
+ BLOCK_CROSS_JUMP
+ return 0;
+ case WIN_STATE_PLACEHOLDER:
+ win->textIndex++;
+ win->state = WIN_STATE_NORMAL;
+ break;
+ case WIN_STATE_NEWLINE:
+ ScrollWindowTextLines(win);
+ win->state = WIN_STATE_NORMAL;
+ BLOCK_CROSS_JUMP
+ return 0;
+ case WIN_STATE_BEGIN:
+ ClearWindowTextLines(win);
+ break;
+ case WIN_STATE_WAIT_SOUND:
+ if (IsSEPlaying())
+ return 0;
+ win->state = WIN_STATE_NORMAL;
+ break;
+ case WIN_STATE_END:
+ return 1;
+ case WIN_STATE_NORMAL:
+ break;
+ default:
+ win->state = WIN_STATE_END;
+ return 1;
+ }
+
+ InterpretText(win);
+
+ switch (win->state)
+ {
+ case WIN_STATE_END:
+ return 1;
+ case WIN_STATE_WAIT_BUTTON:
+ case WIN_STATE_PARAGRAPH:
+ case WIN_STATE_NEWLINE_WAIT:
+ if (PlayerCanInterruptWait(win))
+ return 0;
+ win->delayCounter = 60;
+ break;
+ case WIN_STATE_PAUSE:
+ case WIN_STATE_NEWLINE:
+ case WIN_STATE_WAIT_SOUND:
+ break;
+ default:
+ win->state = WIN_STATE_INTERRUPTIBLE_PAUSE;
+ win->delayCounter = GetTextDelay(win);
+ }
+
+ return 0;
+}
+
+#if defined(ENGLISH)
+#define SUB_800374C_LINE_LENGTH 26
+#elif defined(GERMAN)
+#define SUB_800374C_LINE_LENGTH 27
+#endif
+
+u8 sub_800374C(struct Window *win)
+{
+ u8 retVal;
+
+ sWaitType = 1;
+ sLineLength = SUB_800374C_LINE_LENGTH;
+ retVal = UpdateWindowText(win);
+ sLineLength = 26;
+ sWaitType = 0;
+ return retVal;
+}
+
+u8 sub_8003778(struct Window *win)
+{
+ u8 retVal;
+
+ sWaitType = 2;
+ sLineLength = 26;
+ retVal = UpdateWindowText(win);
+ sWaitType = 0;
+ return retVal;
+}
+
+u8 sub_80037A0(struct Window *win)
+{
+ u8 retVal;
+
+ sWaitType = 3;
+ sLineLength = 17;
+ retVal = UpdateWindowText(win);
+ sLineLength = 26;
+ return retVal;
+}
+
+u32 sub_80037C8(struct Window *win, u8 lineLength)
+{
+ u8 retVal;
+
+ sWaitType = 0;
+ sLineLength = lineLength;
+ retVal = UpdateWindowText(win);
+ sLineLength = 26;
+ return retVal;
+}
+
+static void PrintGlyph_TextMode0(struct Window *win, u32 glyph)
+{
+ AddToCursorX(win, DrawGlyph_TextMode0(win, glyph));
+ if (win->win_field_B)
+ ClipRight(win);
+}
+
+static u8 DrawGlyph_TextMode0(struct Window *win, u32 glyph)
+{
+ u8 pixelsWidth = GetGlyphWidth(win, glyph);
+ u32 tilesWidth = DrawGlyphTiles(win, glyph, pixelsWidth);
+ UpdateTilemap(win, tilesWidth);
+ return pixelsWidth;
+}
+
+static void PrintGlyph_TextMode1(struct Window *win, u32 glyph)
+{
+ sWriteGlyphTilemapFuncs[win->fontNum](win, glyph);
+ win->cursorX += 8;
+}
+
+static void WriteGlyphTilemap_Font0_Font3(struct Window *win, u32 glyph)
+{
+ s16 val = win->tileDataStartOffset + 2 * glyph;
+ WriteGlyphTilemap(win, val, val + 1);
+}
+
+static void WriteGlyphTilemap_Font1_Font4(struct Window *win, u32 glyph)
+{
+ u32 val = glyph * 2;
+ WriteGlyphTilemap(
+ win,
+ win->tileDataStartOffset + sFontType1Map[val],
+ win->tileDataStartOffset + sFontType1Map[val + 1]);
+}
+
+static void WriteGlyphTilemap_Font2_Font5(struct Window *win, u32 glyph)
+{
+ WriteGlyphTilemap(
+ win,
+ win->tileDataStartOffset + 212,
+ win->tileDataStartOffset + glyph);
+}
+
+static void WriteGlyphTilemap_Font6(struct Window *win, u32 glyph)
+{
+ u32 val = glyph * 2;
+ WriteGlyphTilemap(
+ win,
+ win->tileDataStartOffset + sFontType3Map[val],
+ win->tileDataStartOffset + sFontType3Map[val + 1]);
+}
+
+static void PrintGlyph_TextMode2(struct Window *win, u32 glyph)
+{
+ u8 width = GetGlyphWidth(win, glyph);
+ DrawGlyph_TextMode2(win, glyph);
+ AddToCursorX(win, width);
+ if (win->win_field_B)
+ ClipRight(win);
+}
+
+static void DrawGlyph_TextMode2(struct Window *win, u32 glyph)
+{
+ u8 pixelsWidth = GetGlyphWidth(win, glyph);
+ u32 tilesWidth = DrawGlyphTiles(win, glyph, pixelsWidth);
+ UpdateTilemap(win, tilesWidth);
+}
+
+static void LoadFixedWidthGlyph(struct Window *win, u32 glyph, u8 *dest)
+{
+ u8 *upperTile;
+ u8 *lowerTile;
+
+ GetGlyphTilePointers(win->fontNum, win->language, glyph, &upperTile, &lowerTile);
+
+ switch (win->fontNum)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 6:
+ ApplyColors_UnshadowedFont(upperTile, (u32 *)dest, win->foregroundColor, win->backgroundColor);
+ ApplyColors_UnshadowedFont(lowerTile, (u32 *)(dest + 32), win->foregroundColor, win->backgroundColor);
+ break;
+ case 3:
+ case 4:
+ case 5:
+ ApplyColors_ShadowedFont(upperTile, dest, win->foregroundColor, win->shadowColor, win->backgroundColor);
+ ApplyColors_ShadowedFont(lowerTile, dest + 32, win->foregroundColor, win->shadowColor, win->backgroundColor);
+ break;
+ }
+}
+
+static void WriteGlyphTilemap(struct Window *win, u16 upperTileNum, u16 lowerTileNum)
+{
+ u16 *buffer = GetCursorTilemapPointer(win);
+ if (buffer)
+ {
+ u16 palette = (win->paletteNum << 12);
+ buffer[0] = upperTileNum | palette;
+ buffer[32] = lowerTileNum | palette;
+ }
+}
+
+static void GetGlyphTilePointers(u8 fontNum, u8 language, u16 glyph, u8 **upperTilePtr, u8 **lowerTilePtr)
+{
+ u16 index;
+ const struct Font *font;
+
+ if (language == LANGUAGE_JAPANESE)
+ language = 0;
+ else
+ language = 7;
+
+ font = &sFonts[language + fontNum];
+
+ switch (font->type)
+ {
+ case 0:
+ *upperTilePtr = font->glyphs + glyph * font->glyphSize;
+ *lowerTilePtr = *upperTilePtr + font->lowerTileOffset;
+ break;
+ case 1:
+ index = 2 * glyph;
+ *upperTilePtr = font->glyphs + sFontType1Map[index] * font->glyphSize;
+ *lowerTilePtr = font->glyphs + sFontType1Map[index + 1] * font->glyphSize;
+ break;
+ case 2:
+ *upperTilePtr = font->glyphs + 212 * font->glyphSize;
+ *lowerTilePtr = font->glyphs + glyph * font->glyphSize;
+ break;
+ case 3:
+ index = 2 * glyph;
+ *upperTilePtr = font->glyphs + sFontType3Map[index] * font->glyphSize;
+ *lowerTilePtr = font->glyphs + sFontType3Map[index + 1] * font->glyphSize;
+ break;
+ case 4:
+ *upperTilePtr = font->glyphs
+ + (glyph & 0xFFF0) * font->glyphSize
+ + (((glyph &= 0xF) * font->glyphSize) >> 1);
+ *lowerTilePtr = *upperTilePtr + font->lowerTileOffset;
+ break;
+ }
+}
+
+static u16 *GetCursorTilemapPointer(struct Window *win)
+{
+ u16 *ptr = NULL;
+ if (win->tilemap)
+ {
+ u8 x = ((win->left + win->cursorX) >> 3) + win->tilemapLeft;
+ u8 y = ((win->top + win->cursorY) >> 3) + win->tilemapTop;
+ ptr = &win->tilemap[(y * 32) + x];
+ }
+ return ptr;
+}
+
+static void ApplyColors_UnshadowedFont(const u8 *src, u32 *dest, u8 foreground, u8 background)
+{
+ u32 a[2];
+ s32 i;
+ const u8 *srcRows = src;
+
+ a[0] = background;
+ a[1] = foreground;
+
+ for (i = 0; i < 8; i++)
+ {
+ u32 destRow = a[srcRows[i] & 1]
+ | (a[(srcRows[i] >> 1) & 1] << 4)
+ | (a[(srcRows[i] >> 2) & 1] << 8)
+ | (a[(srcRows[i] >> 3) & 1] << 12)
+ | (a[(srcRows[i] >> 4) & 1] << 16)
+ | (a[(srcRows[i] >> 5) & 1] << 20)
+ | (a[(srcRows[i] >> 6) & 1] << 24)
+ | (a[(srcRows[i] >> 7) ] << 28);
+ dest[i] = destRow;
+ }
+}
+
+static void ApplyColors_ShadowedFont(const void *src, void *dest, u8 foreground, u8 shadow, u8 background)
+{
+ u32 a[0x10];
+ s32 i;
+ const u32 *curSrc;
+ u32 *curDest;
+ u32 colorMask;
+
+ a[0x1] = 0x1;
+ a[0x2] = 0x2;
+ a[0x3] = 0x3;
+ a[0x4] = 0x4;
+ a[0x5] = 0x5;
+ a[0x6] = 0x6;
+ a[0x7] = 0x7;
+ a[0x8] = 0x8;
+ a[0x9] = 0x9;
+ a[0xA] = 0xA;
+ a[0xB] = 0xB;
+ a[0xC] = 0xC;
+ a[0xD] = 0xD;
+ a[0x0] = background;
+ a[0xE] = shadow;
+ a[0xF] = foreground;
+
+ colorMask = 0xF;
+
+ curSrc = src;
+ curDest = dest;
+
+ for (i = 7; i >= 0; i--)
+ {
+ u32 row = *curSrc++;
+ u32 recoloredRow = a[row & colorMask]
+ | (a[(row >> 4) & colorMask] << 4)
+ | (a[(row >> 8) & colorMask] << 8)
+ | (a[(row >> 12) & colorMask] << 12)
+ | (a[(row >> 16) & colorMask] << 16)
+ | (a[(row >> 20) & colorMask] << 20)
+ | (a[(row >> 24) & colorMask] << 24)
+ | (a[(row >> 28) ] << 28);
+ *curDest++ = recoloredRow;
+ }
+}
+
+static void SetCursorX(struct Window *win, u8 x)
+{
+ if (win->textMode == 0 && ((win->left + win->cursorX) & 7))
+ win->tileDataOffset += 2;
+ win->cursorX = x;
+}
+
+static void AddToCursorX(struct Window *win, u8 deltaX)
+{
+ if (win->textMode == 0)
+ {
+ u8 x = win->cursorX;
+ win->cursorX += deltaX;
+ if (((win->left + win->cursorX) & 0xF8) != ((win->left + x) & 0xF8))
+ win->tileDataOffset += 2;
+ }
+ else
+ {
+ win->cursorX += deltaX;
+ }
+}
+
+static void AddToCursorY(struct Window *win, u8 deltaY)
+{
+ if (win->textMode == 0 && ((win->left + win->cursorX) & 7))
+ win->tileDataOffset += 2;
+ win->cursorY += deltaY;
+}
+
+static void EraseAtCursor(struct Window *win)
+{
+ switch (win->textMode)
+ {
+ case 0:
+ case 2:
+ DrawGlyphTiles(win, 0, 8);
+ break;
+ case 1:
+ sWriteGlyphTilemapFuncs[win->fontNum](win, 0);
+ break;
+ }
+}
+
+static void ClipLeft(struct Window *win)
+{
+ u32 pixel = win->left & 7;
+ if (win->textMode != 1 && pixel)
+ {
+ const u32 *masks = sGlyphMasks[8][pixel];
+ u32 outsideMask = masks[0];
+ u32 insideMask = ~outsideMask;
+ u32 outside = sGlyphBuffer.background & outsideMask;
+ u16 tileNum = GetCursorTileNum(win, 0, 0);
+ u32 *buffer = (u32 *)(win->tileData + 32 * tileNum);
+ buffer[0] = (buffer[0] & insideMask) | outside;
+ buffer[1] = (buffer[1] & insideMask) | outside;
+ buffer[2] = (buffer[2] & insideMask) | outside;
+ buffer[3] = (buffer[3] & insideMask) | outside;
+ buffer[4] = (buffer[4] & insideMask) | outside;
+ buffer[5] = (buffer[5] & insideMask) | outside;
+ buffer[6] = (buffer[6] & insideMask) | outside;
+ buffer[7] = (buffer[7] & insideMask) | outside;
+ tileNum = GetCursorTileNum(win, 0, 1);
+ buffer = (u32 *)(win->tileData + 32 * tileNum);
+ buffer[0] = (buffer[0] & insideMask) | outside;
+ buffer[1] = (buffer[1] & insideMask) | outside;
+ buffer[2] = (buffer[2] & insideMask) | outside;
+ buffer[3] = (buffer[3] & insideMask) | outside;
+ buffer[4] = (buffer[4] & insideMask) | outside;
+ buffer[5] = (buffer[5] & insideMask) | outside;
+ buffer[6] = (buffer[6] & insideMask) | outside;
+ buffer[7] = (buffer[7] & insideMask) | outside;
+ }
+}
+
+static void ClipRight(struct Window *win)
+{
+ register u8 cursorX asm("r0") = win->cursorX;
+ u8 left = win->left;
+ u32 pixel = (cursorX + left) & 7;
+ if (win->textMode != 1 && pixel)
+ {
+ const u32 *masks = sGlyphMasks[8 - pixel][pixel];
+ u32 insideMask = masks[0];
+ u32 outside = (sGlyphBuffer.background & ~insideMask);
+ u16 tileNum = GetCursorTileNum(win, 0, 0);
+ u32 *buffer = (u32 *)(win->tileData + 32 * tileNum);
+ buffer[0] = (buffer[0] & insideMask) | outside;
+ buffer[1] = (buffer[1] & insideMask) | outside;
+ buffer[2] = (buffer[2] & insideMask) | outside;
+ buffer[3] = (buffer[3] & insideMask) | outside;
+ buffer[4] = (buffer[4] & insideMask) | outside;
+ buffer[5] = (buffer[5] & insideMask) | outside;
+ buffer[6] = (buffer[6] & insideMask) | outside;
+ buffer[7] = (buffer[7] & insideMask) | outside;
+ tileNum = GetCursorTileNum(win, 0, 1);
+ buffer = (u32 *)(win->tileData + 32 * tileNum);
+ buffer[0] = (buffer[0] & insideMask) | outside;
+ buffer[1] = (buffer[1] & insideMask) | outside;
+ buffer[2] = (buffer[2] & insideMask) | outside;
+ buffer[3] = (buffer[3] & insideMask) | outside;
+ buffer[4] = (buffer[4] & insideMask) | outside;
+ buffer[5] = (buffer[5] & insideMask) | outside;
+ buffer[6] = (buffer[6] & insideMask) | outside;
+ buffer[7] = (buffer[7] & insideMask) | outside;
+ UpdateTilemap(win, 1);
+ }
+}
+
+static void InitColors(struct Window *win)
+{
+ u32 i;
+
+ win->backgroundColor = 0;
+ win->shadowColor = 14;
+ win->foregroundColor = 15;
+
+ for (i = 0; i < 16; i++)
+ sGlyphBuffer.colors[i] = i;
+}
+
+static void SetBackgroundColor(struct Window *win, u8 color)
+{
+ u32 val1;
+ u32 val2;
+ u32 val3;
+ win->backgroundColor = color;
+ sGlyphBuffer.colors[0] = color;
+ val1 = color | (color << 4);
+ val2 = val1 | (val1 << 8);
+ val3 = val2 | (val2 << 16);
+ sGlyphBuffer.background = val3;
+}
+
+static void SetShadowColor(struct Window *win, u8 color)
+{
+ win->shadowColor = color;
+ sGlyphBuffer.colors[14] = color;
+}
+
+static void SetForegroundColor(struct Window *win, u8 color)
+{
+ win->foregroundColor = color;
+ sGlyphBuffer.colors[15] = color;
+}
+
+static u8 GetTextDelay(struct Window *win)
+{
+ if (!PlayerCanInterruptWait(win))
+ return 3;
+
+ return sTextSpeedDelays[gSaveBlock2.optionsTextSpeed];
+}
+
+static bool8 PlayerCanInterruptWait(struct Window *win)
+{
+ bool8 retVal = TRUE;
+
+ switch (sWaitType)
+ {
+ case 2:
+ retVal = FALSE;
+ break;
+ case 3:
+ retVal = gIsLinkContest ? FALSE : TRUE;
+ break;
+ case 1:
+ retVal = (gBattleTypeFlags & BATTLE_TYPE_LINK) ? FALSE : TRUE;
+ break;
+ }
+
+ return retVal;
+}
+
+static void ScrollWindowTextLines(struct Window *win)
+{
+ switch (win->textMode)
+ {
+ case 0:
+ ScrollWindowTextLines_TextMode0(win);
+ break;
+ case 1:
+ ScrollWindowTextLines_TextMode1(win);
+ break;
+ case 2:
+ ScrollWindowTextLines_TextMode2(win);
+ break;
+ }
+}
+
+static void ScrollWindowTextLines_TextMode0(struct Window *win)
+{
+ if (win->cursorY == 0)
+ {
+ win->tileDataOffset = 2 * sLineLength + 2;
+ win->cursorX = 0;
+ win->cursorY += 16;
+ }
+ else
+ {
+ if (win->win_field_C & 2)
+ win->tileDataOffset = 2 * sLineLength + 2;
+ else
+ win->tileDataOffset = 2;
+ win->win_field_C = win->win_field_C ^ 2;
+ win->cursorX = 0;
+ DoScroll_TextMode0(win, sLineLength);
+ }
+}
+
+static void DoScroll_TextMode0(struct Window *win, u16 lineLength)
+{
+ u16 *buffer = win->tilemap;
+ u32 val1 = 32 * (win->top >> 3);
+ u32 val2 = (win->left >> 3);
+ u16 fill;
+ buffer += val1 + val2;
+ fill = (win->paletteNum << 12) | GetBlankTileNum(win);
+ CpuCopy16(buffer + 64, buffer, lineLength * 2);
+ CpuCopy16(buffer + 96, buffer + 32, lineLength * 2);
+ CpuFill16(fill, buffer + 64, lineLength * 2);
+ CpuFill16(fill, buffer + 96, lineLength * 2);
+}
+
+static void ScrollWindowTextLines_TextMode1(struct Window *win)
+{
+ if (win->cursorY == 0)
+ {
+ win->cursorX = 0;
+ win->cursorY += 16;
+ }
+ else
+ {
+ win->win_field_C ^= 2;
+ win->cursorX = 0;
+ DoScroll_TextMode1(win, sLineLength);
+ }
+}
+
+static void DoScroll_TextMode1(struct Window *win, u16 lineLength)
+{
+ u16 *buffer = GetCursorTilemapPointer(win);
+ u16 *dest = buffer - 32;
+ u16 fill = (win->paletteNum << 12) | GetBlankTileNum(win);
+ CpuCopy16(buffer + 32, dest, lineLength * 2);
+ CpuCopy16(buffer + 64, buffer, lineLength * 2);
+ CpuFill16(fill, buffer + 32, lineLength * 2);
+ CpuFill16(fill, buffer + 64, lineLength * 2);
+}
+
+static void ScrollWindowTextLines_TextMode2(struct Window *win)
+{
+ if (win->cursorY == 0)
+ {
+ win->cursorX = 0;
+ win->cursorY += 16;
+ }
+ else
+ {
+ win->win_field_C ^= 2;
+ win->cursorX = 0;
+ DoScroll_TextMode2(win, sLineLength);
+ }
+}
+
+static void DoScroll_TextMode2(struct Window *win, u8 lineLength)
+{
+ u8 i;
+ u8 *buf1 = win->tileData + 32 * GetCursorTileNum(win, 0, -2);
+ u8 *buf2 = win->tileData + 32 * GetCursorTileNum(win, 0, 0);
+ u8 *buf4;
+ u16 *buf3;
+ u16 a[4];
+
+ CpuFastCopy(buf2, buf1, 32 * lineLength);
+ CpuFastFill(sGlyphBuffer.background, buf2, 32 * lineLength);
+ buf4 = buf2 + 32 * win->width;
+ CpuFastCopy(buf4, buf1 + 32 * win->width, 32 * lineLength);
+ CpuFastFill(sGlyphBuffer.background, buf4, 32 * lineLength);
+
+ buf3 = GetCursorTilemapPointer(win) - 64;
+
+ a[0] = (win->tileDataStartOffset + win->tileDataOffset
+ + ((win->top >> 3) * win->width)
+ + (win->left >> 3))
+ | (win->paletteNum << 12);
+ a[1] = a[0] + win->width;
+ a[2] = a[1] + win->width;
+ a[3] = a[2] + win->width;
+
+ for (i = 0; i < lineLength; i++)
+ {
+ buf3[0] = a[0]++;
+ buf3[32] = a[1]++;
+ buf3[64] = a[2]++;
+ buf3[96] = a[3]++;
+ buf3++;
+ }
+}
+
+void ClearWindowTextLines(struct Window *win)
+{
+ switch (win->textMode)
+ {
+ case 0:
+ ClearWindowTextLines_TextMode0_TextMode1(win, sLineLength);
+ win->tileDataOffset = 2;
+ break;
+ case 1:
+ ClearWindowTextLines_TextMode0_TextMode1(win, sLineLength);
+ break;
+ case 2:
+ ClearWindowTextLines_TextMode2(win, sLineLength);
+ break;
+ }
+}
+
+static void ClearWindowTextLines_TextMode0_TextMode1(struct Window *win, u8 lineLength)
+{
+ u8 i;
+ u16 *buffer;
+ u16 fill;
+
+ win->cursorX = 0;
+ win->cursorY = 0;
+ win->win_field_C = 0;
+
+ buffer = GetCursorTilemapPointer(win);
+ fill = GetBlankTileNum(win) | (win->paletteNum << 12);
+
+ for (i = 0; i < 4; i++)
+ {
+ u8 j;
+ for (j = 0; j < lineLength; j++)
+ buffer[j] = fill;
+ buffer += 32;
+ }
+}
+
+static void ClearWindowTextLines_TextMode2(struct Window *win, u8 lineLength)
+{
+ u8 *buffer;
+
+ win->cursorX = 0;
+ win->cursorY = 0;
+ win->win_field_C = 0;
+
+ buffer = win->tileData + 32 * GetCursorTileNum(win, 0, 0);
+ CpuFastFill(sGlyphBuffer.background, buffer, 32 * lineLength);
+ buffer += 32 * win->width;
+ CpuFastFill(sGlyphBuffer.background, buffer, 32 * lineLength);
+ buffer += 32 * win->width;
+ CpuFastFill(sGlyphBuffer.background, buffer, 32 * lineLength);
+ buffer += 32 * win->width;
+ CpuFastFill(sGlyphBuffer.background, buffer, 32 * lineLength);
+}
+
+static void DrawDownArrow(struct Window *win)
+{
+ if (PlayerCanInterruptWait(win))
+ {
+ const u32 *downArrowTiles = &sDownArrowTiles[((win->downArrowCounter & 0x0F00) >> 8) * 16];
+
+ switch (win->textMode)
+ {
+ case 1:
+ {
+ u8 *buffer;
+ u16 tileNum = win->tileDataStartOffset + 254;
+ if (win->fontNum == 0 || win->fontNum == 3)
+ tileNum *= 2;
+ buffer = win->tileData + 32 * tileNum;
+ ApplyColors_ShadowedFont(downArrowTiles, buffer, win->foregroundColor, win->shadowColor, win->backgroundColor);
+ ApplyColors_ShadowedFont(downArrowTiles + 8, buffer + 32, win->foregroundColor, win->shadowColor, win->backgroundColor);
+ WriteGlyphTilemap(win, tileNum, tileNum + 1);
+ break;
+ }
+ case 0:
+ case 2:
+ {
+ struct GlyphTileInfo glyphTileInfo;
+ glyphTileInfo.textMode = win->textMode;
+ glyphTileInfo.startPixel = (win->left + win->cursorX) & 7;
+ if (glyphTileInfo.startPixel != 0)
+ {
+ u8 *upperTile;
+ u8 *lowerTile;
+ GetGlyphTilePointers(win->fontNum, win->language, 0, &upperTile, &lowerTile);
+ glyphTileInfo.width = 8 - glyphTileInfo.startPixel;
+ glyphTileInfo.src = upperTile;
+ glyphTileInfo.dest = (u32 *)(win->tileData + 32 * GetCursorTileNum(win, 1, 0));
+ glyphTileInfo.colors = sGlyphBuffer.colors;
+ DrawGlyphTile_ShadowedFont(&glyphTileInfo);
+ glyphTileInfo.src = lowerTile;
+ glyphTileInfo.dest = (u32 *)(win->tileData + 32 * GetCursorTileNum(win, 1, 1));
+ DrawGlyphTile_ShadowedFont(&glyphTileInfo);
+ }
+ glyphTileInfo.width = 8;
+ glyphTileInfo.src = (u8 *)downArrowTiles;
+ glyphTileInfo.dest = (u32 *)(win->tileData + 32 * GetCursorTileNum(win, 0, 0));
+ glyphTileInfo.colors = sGlyphBuffer.colors;
+ DrawGlyphTile_ShadowedFont(&glyphTileInfo);
+ glyphTileInfo.src += 32;
+ glyphTileInfo.dest = (u32 *)(win->tileData + 32 * GetCursorTileNum(win, 0, 1));
+ DrawGlyphTile_ShadowedFont(&glyphTileInfo);
+ if (glyphTileInfo.startPixel != 0)
+ UpdateTilemap(win, 2);
+ else
+ UpdateTilemap(win, 1);
+ break;
+ }
+ }
+ }
+}
+
+static u8 WaitWithDownArrow(struct Window *win)
+{
+ u8 retVal = 1;
+
+ if (!PlayerCanInterruptWait(win))
+ {
+ win->delayCounter--;
+ if (!win->delayCounter)
+ {
+ TryEraseDownArrow(win);
+ }
+ else
+ {
+ DrawMovingDownArrow(win);
+ retVal = 0;
+ }
+ }
+ else
+ {
+ if (gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ TryEraseDownArrow(win);
+ }
+ else
+ {
+ DrawMovingDownArrow(win);
+ retVal = 0;
+ }
+ }
+
+ return retVal;
+}
+
+static void DrawInitialDownArrow(struct Window *win)
+{
+ win->downArrowCounter = 0;
+ DrawDownArrow(win);
+}
+
+static void DrawMovingDownArrow(struct Window *win)
+{
+ u16 downArrowPos = (win->downArrowCounter & 0x0F00) >> 8;
+ u16 wait = win->downArrowCounter & 0x000F;
+ u16 newVal;
+
+ wait++;
+
+ if (wait == 6)
+ {
+ wait = 0;
+ downArrowPos++;
+ if (downArrowPos > 3)
+ downArrowPos = 0;
+ win->downArrowCounter = downArrowPos << 8;
+ DrawDownArrow(win);
+ }
+
+ newVal = downArrowPos << 8;
+ newVal |= wait;
+
+ win->downArrowCounter = newVal;
+}
+
+static void TryEraseDownArrow(struct Window *win)
+{
+ win->downArrowCounter = 0;
+ if (PlayerCanInterruptWait(win) == TRUE)
+ EraseAtCursor(win);
+}
+
+u16 GetWindowTilemapEntry(struct Window *win, u8 x, u8 y)
+{
+ u16 *tilemap = win->tilemap;
+ return tilemap[32 * y + x];
+}
+
+void DrawWindowRect(struct Window *win, u16 tilemapEntry, u8 left, u8 top, u8 right, u8 bottom)
+{
+ u8 i;
+ u16 *buffer = &win->tilemap[top * 32];
+
+ for (i = left; i <= right; i++)
+ buffer[i] = tilemapEntry;
+
+ for (i = top + 1; i < bottom - 1; i++)
+ {
+ buffer += 32;
+ buffer[left] = tilemapEntry;
+ buffer[right] = tilemapEntry;
+ }
+
+ if (top != bottom)
+ {
+ buffer += 32;
+ for (i = left; i <= right; i++)
+ buffer[i] = tilemapEntry;
+ }
+}
+
+void DrawWindowRect_DefaultPalette(struct Window *win, u16 tileNum, u8 left, u8 top, u8 right, u8 bottom)
+{
+ DrawWindowRect(win, (win->paletteNum << 12) | tileNum, left, top, right, bottom);
+}
+
+void FillWindowRect(struct Window *win, u16 tilemapEntry, u8 left, u8 top, u8 right, u8 bottom)
+{
+ u16 *buffer = &win->tilemap[top * 32];
+ while (top++ <= bottom)
+ {
+ u8 j;
+ for (j = left; j <= right; j++)
+ buffer[j] = tilemapEntry;
+ buffer += 32;
+ }
+}
+
+void FillWindowRect_DefaultPalette(struct Window *win, u16 tileNum, u8 left, u8 top, u8 right, u8 bottom)
+{
+ FillWindowRect(win, (win->paletteNum << 12) | tileNum, left, top, right, bottom);
+}
+
+void ZeroFillWindowRect(struct Window *win, u8 left, u8 top, u8 right, u8 bottom)
+{
+ FillWindowRect_DefaultPalette(win, 0, left, top, right, bottom);
+}
+
+void FillWindowRectWithBlankTile(struct Window *win, u8 left, u8 top, u8 right, u8 bottom)
+{
+ u16 tileNum = GetBlankTileNum(win);
+ FillWindowRect_DefaultPalette(win, tileNum, left, top, right, bottom);
+}
+
+static u16 GetBlankTileNum(struct Window *win)
+{
+ u16 retVal = win->tileDataStartOffset;
+
+ switch (win->textMode)
+ {
+ case 0:
+ break;
+ case 2:
+ retVal++;
+ break;
+ case 1:
+ switch (win->fontNum)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ retVal += 212;
+ case 0:
+ case 3:
+ case 6:
+ break;
+ default:
+ retVal = 0;
+ }
+ break;
+ }
+
+ return retVal;
+}
+
+static s32 sub_80048D8(struct Window *win, u8 x, u8 y)
+{
+ win->cursorX = x;
+ win->cursorY = y & 0xF8;
+}
+
+static u8 GetGlyphWidth(struct Window *win, u32 glyph)
+{
+ u8 width = 8;
+
+#ifdef BUGFIX_GLYPHWIDTH
+ if (win->language != LANGUAGE_JAPANESE)
+#else
+ if (win->language == LANGUAGE_ENGLISH)
+#endif
+ {
+ width = win->spacing;
+ if (!win->spacing)
+ {
+ switch (win->fontNum)
+ {
+ case 3:
+ width = sFont3Widths[glyph];
+ break;
+ case 4:
+ case 5:
+ width = sFont4Widths[sFontType1Map[2 * glyph + 1]];
+ break;
+ case 0:
+ width = sFont0Widths[glyph];
+ break;
+ case 1:
+ case 2:
+ width = sFont1Widths[sFontType1Map[2 * glyph + 1]];
+ break;
+ case 6:
+ width = 8;
+ break;
+ default:
+ width = 8;
+ }
+ }
+ }
+
+ return width;
+}
+
+u8 GetExtCtrlCodeLength(u8 code)
+{
+ u8 length = 0;
+ if (code <= 0x16)
+ length = sExtCtrlCodeLengths[code];
+ return length;
+}
+
+u8 *AlignInt1(struct Window *win, u8 *dest, s32 value, u8 alignAmount, u8 alignType)
+{
+ u8 temp[16];
+ u8 width;
+ switch (alignType)
+ {
+ case 0:
+ ConvertIntToDecimalString(temp, value);
+ dest = StringCopy(dest, temp);
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = alignAmount;
+ dest += 3;
+ *dest = 0xFF;
+ break;
+ case 1:
+ ConvertIntToDecimalString(temp, value);
+ width = GetStringWidth(win, temp);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = alignAmount - width;
+ dest += 3;
+ }
+ dest = StringCopy(dest, temp);
+ break;
+ case 2:
+ ConvertIntToDecimalString(temp, value);
+ width = GetStringWidth(win, temp);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = (alignAmount - width) / 2;
+ dest += 3;
+ }
+ dest = StringCopy(dest, temp);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = alignAmount;
+ dest += 3;
+ *dest = 0xFF;
+ }
+ break;
+ }
+ return dest;
+}
+
+u8 *AlignInt2(struct Window *win, u8 *dest, s32 value, u8 alignAmount, u8 alignType)
+{
+ u8 temp[16];
+ u8 width;
+ switch (alignType)
+ {
+ case 0:
+ ConvertIntToDecimalString(temp, value);
+ width = GetStringWidth(win, temp);
+ dest = StringCopy(dest, temp);
+ dest[0] = 0xFC;
+ dest[1] = 17;
+ dest[2] = alignAmount - width;
+ dest += 3;
+ *dest = 0xFF;
+ break;
+ case 1:
+ ConvertIntToDecimalString(temp, value);
+ width = GetStringWidth(win, temp);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 17;
+ dest[2] = alignAmount - width;
+ dest += 3;
+ }
+ dest = StringCopy(dest, temp);
+ break;
+ case 2:
+ ConvertIntToDecimalString(temp, value);
+ width = GetStringWidth(win, temp);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 17;
+ dest[2] = (alignAmount - width) / 2;
+ dest += 3;
+ }
+ dest = StringCopy(dest, temp);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 17;
+ dest[2] = (alignAmount - width) / 2;
+ dest += 3;
+ *dest = 0xFF;
+ }
+ break;
+ }
+ return dest;
+}
+
+u8 *AlignString(struct Window *win, u8 *dest, const u8 *src, u8 alignAmount, u8 alignType)
+{
+ u8 width;
+ switch (alignType)
+ {
+ case 0:
+ dest = StringCopy(dest, src);
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = alignAmount;
+ dest += 3;
+ *dest = 0xFF;
+ break;
+ case 1:
+ width = GetStringWidth(win, src);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = alignAmount - width;
+ dest += 3;
+ }
+ dest = StringCopy(dest, src);
+ break;
+ case 2:
+ width = GetStringWidth(win, src);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = (alignAmount - width) / 2;
+ dest += 3;
+ }
+ dest = StringCopy(dest, src);
+ if (alignAmount > width)
+ {
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = alignAmount;
+ dest += 3;
+ *dest = 0xFF;
+ }
+ break;
+ }
+ return dest;
+}
+
+u8 GetStringWidth(struct Window *win, const u8 *s)
+{
+ u8 width = 0;
+ u8 savedFontNum = win->fontNum;
+ u8 savedCharset = win->language;
+ u8 savedSpacing = win->spacing;
+ s32 i = 0;
+
+ while (s[i] != 0xFF)
+ {
+ u8 c = s[i];
+ switch (c)
+ {
+ case 0xFD:
+ {
+ u8 temp;
+ i++;
+ temp = win->language;
+ width += GetStringWidth(win, GetExpandedPlaceholder(s[i]));
+ win->language = temp;
+ i++;
+ break;
+ }
+ case 0xFC:
+ i++;
+ switch (s[i])
+ {
+ case 6:
+ win->fontNum = s[i + 1];
+ break;
+ case 7:
+ win->fontNum = win->config->fontNum;
+ break;
+ case 0x11:
+ width += s[i + 1];
+ break;
+ case 0x12:
+ case 0x13:
+ if (width < s[i + 1])
+ width = s[i + 1];
+ break;
+ case 0x14:
+ win->spacing = s[i + 1];
+ break;
+ case 0x15:
+ win->language = LANGUAGE_JAPANESE;
+ break;
+ case 0x16:
+ win->language = GAME_LANGUAGE;
+ break;
+ }
+
+ i += GetExtCtrlCodeLength(s[i]);
+ break;
+ default:
+ i++;
+ width += GetGlyphWidth(win, c);
+ }
+ }
+
+ win->spacing = savedSpacing;
+ win->language = savedCharset;
+ win->fontNum = savedFontNum;
+
+ return width;
+}
+
+u8 sub_8004D04(struct Window *win, const u8 *text, u16 tileDataStartOffset, u8 left, u16 top, u32 a6)
+{
+ sub_8002E4C(win, text, tileDataStartOffset, left, top, a6);
+ return sub_8002F44(win);
+}
+
+u8 sub_8004D38(struct Window *win, const u8 *text, u16 tileDataStartOffset, u8 left, u8 top)
+{
+ u8 width = GetStringWidth(win, text);
+ InitWindow(win, text, tileDataStartOffset, left - ((u32)(width + 7) >> 3), top);
+ EraseAtCursor(win);
+ width &= 7;
+ if (width)
+ width = 8 - width;
+ sub_80048D8(win, width, 0);
+ return sub_8002F44(win);
+}
+
+u8 sub_8004DB0(struct Window *win, const u8 *text, u16 tileDataStartOffset, u8 left, u8 top, u16 a6)
+{
+ register u32 val asm("r5") = (u8)((a6 >> 1) - (GetStringWidth(win, text) >> 1));
+ left += (val >> 3);
+ InitWindow(win, text, tileDataStartOffset, left, top);
+ EraseAtCursor(win);
+ sub_80048D8(win, val & 7, 0);
+ return sub_8002F44(win);
+}
+
+u8 sub_8004E24(struct Window *win)
+{
+ return win->paletteNum;
+}
+
+void sub_8004E28(struct Window *win, u8 *foreground, u8 *background, u8 *shadow)
+{
+ *foreground = win->foregroundColor;
+ *background = win->backgroundColor;
+ *shadow = win->shadowColor;
+}
+
+void sub_8004E3C(struct WindowConfig *winConfig, u8 *tileData, const u8 *text)
+{
+ sTempWindow.config = winConfig;
+ InitWindow(&sTempWindow, text, 0, 0, 0);
+ sTempWindow.tileData = tileData;
+ sub_8002F44(&sTempWindow);
+}
+
+u8 GetStringWidthGivenWindowConfig(struct WindowConfig *winConfig, const u8 *s)
+{
+ sTempWindow.config = winConfig;
+ InitWindow(&sTempWindow, s, 0, 0, 0);
+ return GetStringWidth(&sTempWindow, s);
+}
+
+void ConvertInternationalString(u8 *s, u8 language)
+{
+ if (language == LANGUAGE_JAPANESE)
+ {
+ u8 i;
+
+ StripExtCtrlCodes(s);
+ i = StringLength(s);
+ s[i++] = 0xFC;
+ s[i++] = 22;
+ s[i++] = 0xFF;
+
+ i--;
+
+ while (i != (u8)-1)
+ {
+ s[i + 2] = s[i];
+ i--;
+ }
+
+ s[0] = 0xFC;
+ s[1] = 21;
+ }
+}
+
+void StripExtCtrlCodes(u8 *str)
+{
+ u16 srcIndex = 0;
+ u16 destIndex = 0;
+ while (str[srcIndex] != 0xFF)
+ {
+ if (str[srcIndex] == 0xFC)
+ {
+ srcIndex++;
+ srcIndex += GetExtCtrlCodeLength(str[srcIndex]);
+ }
+ else
+ {
+ str[destIndex++] = str[srcIndex++];
+ }
+ }
+ str[destIndex] = 0xFF;
+}
+
+static const u8 *SkipExtCtrlCode(const u8 *s)
+{
+ while (*s == 0xFC)
+ {
+ s++;
+ s += GetExtCtrlCodeLength(*s);
+ }
+
+ return s;
+}
+
+s32 StringCompareWithoutExtCtrlCodes(const u8 *str1, const u8 *str2)
+{
+ s32 retVal = 0;
+
+ while (1)
+ {
+ str1 = SkipExtCtrlCode(str1);
+ str2 = SkipExtCtrlCode(str2);
+
+ if (*str1 > *str2)
+ break;
+
+ if (*str1 < *str2)
+ {
+ retVal = -1;
+ if (*str2 == 0xFF)
+ retVal = 1;
+ }
+
+ if (*str1 == 0xFF)
+ return retVal;
+
+ str1++;
+ str2++;
+ }
+
+ retVal = 1;
+
+ if (*str1 == 0xFF)
+ retVal = -1;
+
+ return retVal;
+}
+
+u8 sub_8004FD0(struct Window *win, u8 *dest, const u8 *src, u16 tileDataStartOffset, u8 left, u16 top, u8 width, u32 a8)
+{
+ u8 newlineCount = 0;
+ u8 extCtrlCodeLength;
+ u8 *start;
+ u32 endsWithoutNewline;
+
+ if (dest == NULL)
+ dest = gStringVar4;
+
+ start = dest;
+ endsWithoutNewline = FALSE;
+
+ while (*src != 0xFF)
+ {
+ switch (*src)
+ {
+ default:
+ *dest = *src;
+ dest++;
+ src++;
+ endsWithoutNewline = TRUE;
+ break;
+ case 0xFC:
+ extCtrlCodeLength = GetExtCtrlCodeLength(src[1]) + 1;
+ memcpy(dest, src, extCtrlCodeLength);
+ dest += extCtrlCodeLength;
+ src += extCtrlCodeLength;
+ break;
+ case 0xFE:
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = width;
+ dest[3] = 0xFE;
+ dest += 4;
+ src++;
+ newlineCount++;
+ endsWithoutNewline = FALSE;
+ break;
+ }
+ }
+
+ dest[0] = 0xFC;
+ dest[1] = 19;
+ dest[2] = width;
+ dest[3] = 0xFF;
+
+ if (endsWithoutNewline)
+ newlineCount++;
+
+ sub_8002E4C(win, start, tileDataStartOffset, left, top, a8);
+ sub_8002F44(win);
+
+ return newlineCount;
+}
+
+static s32 DrawGlyphTile_UnshadowedFont(struct GlyphTileInfo *glyphTileInfo)
+{
+ struct GlyphBuffer *glyphBuffer = &sGlyphBuffer;
+ u32 colors[2];
+ u32 *buffer = glyphTileInfo->dest;
+ const u32 *masks = sGlyphMasks[glyphTileInfo->width][glyphTileInfo->startPixel];
+ u32 mask1 = masks[0] | masks[2];
+
+ glyphBuffer->pixelRows[0] = buffer[0] & mask1;
+ glyphBuffer->pixelRows[1] = buffer[1] & mask1;
+ glyphBuffer->pixelRows[2] = buffer[2] & mask1;
+ glyphBuffer->pixelRows[3] = buffer[3] & mask1;
+ glyphBuffer->pixelRows[4] = buffer[4] & mask1;
+ glyphBuffer->pixelRows[5] = buffer[5] & mask1;
+ glyphBuffer->pixelRows[6] = buffer[6] & mask1;
+ glyphBuffer->pixelRows[7] = buffer[7] & mask1;
+
+ if (glyphTileInfo->startPixel + glyphTileInfo->width > 8)
+ {
+ u32 mask2 = masks[1];
+ if (glyphTileInfo->textMode == 2)
+ {
+ glyphBuffer->pixelRows[8] = buffer[8] & mask2;
+ glyphBuffer->pixelRows[9] = buffer[9] & mask2;
+ glyphBuffer->pixelRows[10] = buffer[10] & mask2;
+ glyphBuffer->pixelRows[11] = buffer[11] & mask2;
+ glyphBuffer->pixelRows[12] = buffer[12] & mask2;
+ glyphBuffer->pixelRows[13] = buffer[13] & mask2;
+ glyphBuffer->pixelRows[14] = buffer[14] & mask2;
+ glyphBuffer->pixelRows[15] = buffer[15] & mask2;
+ }
+ else
+ {
+ glyphBuffer->pixelRows[8] = buffer[16] & mask2;
+ glyphBuffer->pixelRows[9] = buffer[17] & mask2;
+ glyphBuffer->pixelRows[10] = buffer[18] & mask2;
+ glyphBuffer->pixelRows[11] = buffer[19] & mask2;
+ glyphBuffer->pixelRows[12] = buffer[20] & mask2;
+ glyphBuffer->pixelRows[13] = buffer[21] & mask2;
+ glyphBuffer->pixelRows[14] = buffer[22] & mask2;
+ glyphBuffer->pixelRows[15] = buffer[23] & mask2;
+ }
+ }
+
+ colors[0] = glyphTileInfo->colors[0];
+ colors[1] = glyphTileInfo->colors[15];
+
+ sShiftGlyphTileUnshadowedFuncs[glyphTileInfo->width](glyphBuffer, glyphTileInfo->src, colors, glyphTileInfo->startPixel);
+
+ buffer[0] = glyphBuffer->pixelRows[0];
+ buffer[1] = glyphBuffer->pixelRows[1];
+ buffer[2] = glyphBuffer->pixelRows[2];
+ buffer[3] = glyphBuffer->pixelRows[3];
+ buffer[4] = glyphBuffer->pixelRows[4];
+ buffer[5] = glyphBuffer->pixelRows[5];
+ buffer[6] = glyphBuffer->pixelRows[6];
+ buffer[7] = glyphBuffer->pixelRows[7];
+
+ if (glyphTileInfo->startPixel + glyphTileInfo->width > 8)
+ {
+ if (glyphTileInfo->textMode != 2)
+ buffer += 8;
+ buffer[8] = glyphBuffer->pixelRows[8];
+ buffer[9] = glyphBuffer->pixelRows[9];
+ buffer[10] = glyphBuffer->pixelRows[10];
+ buffer[11] = glyphBuffer->pixelRows[11];
+ buffer[12] = glyphBuffer->pixelRows[12];
+ buffer[13] = glyphBuffer->pixelRows[13];
+ buffer[14] = glyphBuffer->pixelRows[14];
+ buffer[15] = glyphBuffer->pixelRows[15];
+ }
+
+ return (glyphTileInfo->startPixel + glyphTileInfo->width) / 8;
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width0(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *a3, u8 startPixel)
+{
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width1(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = colors[src[i] >> 7];
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width2(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 7) & 1] << 0)
+ | (colors[(src[i] >> 6) & 1] << 4);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width3(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ // XXX: why 4?
+ u32 val = (colors[(src[i] >> 7) & 1] << 0)
+ | (colors[(src[i] >> 6) & 1] << 4)
+ | (colors[(src[i] >> 5) & 1] << 8)
+ | (colors[(src[i] >> 4) & 1] << 12);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width4(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 7) & 1] << 0)
+ | (colors[(src[i] >> 6) & 1] << 4)
+ | (colors[(src[i] >> 5) & 1] << 8)
+ | (colors[(src[i] >> 4) & 1] << 12);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width5(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 7) & 1] << 0)
+ | (colors[(src[i] >> 6) & 1] << 4)
+ | (colors[(src[i] >> 5) & 1] << 8)
+ | (colors[(src[i] >> 4) & 1] << 12)
+ | (colors[(src[i] >> 3) & 1] << 16);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width6(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 7) & 1] << 0)
+ | (colors[(src[i] >> 6) & 1] << 4)
+ | (colors[(src[i] >> 5) & 1] << 8)
+ | (colors[(src[i] >> 4) & 1] << 12)
+ | (colors[(src[i] >> 3) & 1] << 16)
+ | (colors[(src[i] >> 2) & 1] << 20);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width7(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 7) & 1] << 0)
+ | (colors[(src[i] >> 6) & 1] << 4)
+ | (colors[(src[i] >> 5) & 1] << 8)
+ | (colors[(src[i] >> 4) & 1] << 12)
+ | (colors[(src[i] >> 3) & 1] << 16)
+ | (colors[(src[i] >> 2) & 1] << 20)
+ | (colors[(src[i] >> 1) & 1] << 24);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_UnshadowedFont_Width8(struct GlyphBuffer *glyphBuffer, u8 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 7) & 1] << 0)
+ | (colors[(src[i] >> 6) & 1] << 4)
+ | (colors[(src[i] >> 5) & 1] << 8)
+ | (colors[(src[i] >> 4) & 1] << 12)
+ | (colors[(src[i] >> 3) & 1] << 16)
+ | (colors[(src[i] >> 2) & 1] << 20)
+ | (colors[(src[i] >> 1) & 1] << 24)
+ | (colors[(src[i] >> 0) & 1] << 28);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static s32 DrawGlyphTile_ShadowedFont(struct GlyphTileInfo *glyphTileInfo)
+{
+ struct GlyphBuffer *glyphBuffer = &sGlyphBuffer;
+ u32 *buffer = glyphTileInfo->dest;
+ const u32 *masks = sGlyphMasks[glyphTileInfo->width][glyphTileInfo->startPixel];
+ u32 mask1 = masks[0] | masks[2];
+
+ glyphBuffer->pixelRows[0] = buffer[0] & mask1;
+ glyphBuffer->pixelRows[1] = buffer[1] & mask1;
+ glyphBuffer->pixelRows[2] = buffer[2] & mask1;
+ glyphBuffer->pixelRows[3] = buffer[3] & mask1;
+ glyphBuffer->pixelRows[4] = buffer[4] & mask1;
+ glyphBuffer->pixelRows[5] = buffer[5] & mask1;
+ glyphBuffer->pixelRows[6] = buffer[6] & mask1;
+ glyphBuffer->pixelRows[7] = buffer[7] & mask1;
+
+ if (glyphTileInfo->startPixel + glyphTileInfo->width > 8)
+ {
+ u32 mask2 = masks[1];
+ if (glyphTileInfo->textMode == 2)
+ {
+ glyphBuffer->pixelRows[8] = buffer[8] & mask2;
+ glyphBuffer->pixelRows[9] = buffer[9] & mask2;
+ glyphBuffer->pixelRows[10] = buffer[10] & mask2;
+ glyphBuffer->pixelRows[11] = buffer[11] & mask2;
+ glyphBuffer->pixelRows[12] = buffer[12] & mask2;
+ glyphBuffer->pixelRows[13] = buffer[13] & mask2;
+ glyphBuffer->pixelRows[14] = buffer[14] & mask2;
+ glyphBuffer->pixelRows[15] = buffer[15] & mask2;
+ }
+ else
+ {
+ glyphBuffer->pixelRows[8] = buffer[16] & mask2;
+ glyphBuffer->pixelRows[9] = buffer[17] & mask2;
+ glyphBuffer->pixelRows[10] = buffer[18] & mask2;
+ glyphBuffer->pixelRows[11] = buffer[19] & mask2;
+ glyphBuffer->pixelRows[12] = buffer[20] & mask2;
+ glyphBuffer->pixelRows[13] = buffer[21] & mask2;
+ glyphBuffer->pixelRows[14] = buffer[22] & mask2;
+ glyphBuffer->pixelRows[15] = buffer[23] & mask2;
+ }
+ }
+
+ sShiftGlyphTileShadowedFuncs[glyphTileInfo->width](glyphBuffer, (u32 *)glyphTileInfo->src, glyphTileInfo->colors, glyphTileInfo->startPixel);
+
+ buffer[0] = glyphBuffer->pixelRows[0];
+ buffer[1] = glyphBuffer->pixelRows[1];
+ buffer[2] = glyphBuffer->pixelRows[2];
+ buffer[3] = glyphBuffer->pixelRows[3];
+ buffer[4] = glyphBuffer->pixelRows[4];
+ buffer[5] = glyphBuffer->pixelRows[5];
+ buffer[6] = glyphBuffer->pixelRows[6];
+ buffer[7] = glyphBuffer->pixelRows[7];
+
+ if (glyphTileInfo->startPixel + glyphTileInfo->width > 8)
+ {
+ if (glyphTileInfo->textMode != 2)
+ buffer += 8;
+ buffer[8] = glyphBuffer->pixelRows[8];
+ buffer[9] = glyphBuffer->pixelRows[9];
+ buffer[10] = glyphBuffer->pixelRows[10];
+ buffer[11] = glyphBuffer->pixelRows[11];
+ buffer[12] = glyphBuffer->pixelRows[12];
+ buffer[13] = glyphBuffer->pixelRows[13];
+ buffer[14] = glyphBuffer->pixelRows[14];
+ buffer[15] = glyphBuffer->pixelRows[15];
+ }
+
+ return (glyphTileInfo->startPixel + glyphTileInfo->width) / 8;
+}
+
+static void ShiftGlyphTile_ShadowedFont_Width0(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+}
+
+static void ShiftGlyphTile_ShadowedFont_Width1(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = colors[src[i] & 0xF];
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_ShadowedFont_Width2(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 0) & 0xF] << 0)
+ | (colors[(src[i] >> 4) & 0xF] << 4);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_ShadowedFont_Width3(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 0) & 0xF] << 0)
+ | (colors[(src[i] >> 4) & 0xF] << 4)
+ | (colors[(src[i] >> 8) & 0xF] << 8);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+static void ShiftGlyphTile_ShadowedFont_Width4(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ u32 val = (colors[(src[i] >> 0) & 0xF] << 0)
+ | (colors[(src[i] >> 4) & 0xF] << 4)
+ | (colors[(src[i] >> 8) & 0xF] << 8)
+ | (colors[(src[i] >> 12) & 0xF] << 12);
+ u32 *dest = &glyphBuffer->pixelRows[i];
+ dest[0] |= val << shiftAmount->left;
+ dest[8] |= val >> shiftAmount->right;
+ }
+}
+
+#define SHIFT_GLYPH_WIDTH5_STEP(i) \
+val = (colors[(src[i] >> 0) & 0xF] << 0) \
+ | (colors[(src[i] >> 4) & 0xF] << 4) \
+ | (colors[(src[i] >> 8) & 0xF] << 8) \
+ | (colors[(src[i] >> 12) & 0xF] << 12) \
+ | (colors[(src[i] >> 16) & 0xF] << 16); \
+glyphBuffer->pixelRows[i] |= val << shiftAmount->left; \
+glyphBuffer->pixelRows[i + 8] |= val >> shiftAmount->right; \
+
+static void ShiftGlyphTile_ShadowedFont_Width5(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u32 val;
+ SHIFT_GLYPH_WIDTH5_STEP(0)
+ SHIFT_GLYPH_WIDTH5_STEP(1)
+ SHIFT_GLYPH_WIDTH5_STEP(2)
+ SHIFT_GLYPH_WIDTH5_STEP(3)
+ SHIFT_GLYPH_WIDTH5_STEP(4)
+ SHIFT_GLYPH_WIDTH5_STEP(5)
+ SHIFT_GLYPH_WIDTH5_STEP(6)
+ SHIFT_GLYPH_WIDTH5_STEP(7)
+}
+
+#define SHIFT_GLYPH_WIDTH6_STEP(i) \
+val = (colors[(src[i] >> 0) & 0xF] << 0) \
+ | (colors[(src[i] >> 4) & 0xF] << 4) \
+ | (colors[(src[i] >> 8) & 0xF] << 8) \
+ | (colors[(src[i] >> 12) & 0xF] << 12) \
+ | (colors[(src[i] >> 16) & 0xF] << 16) \
+ | (colors[(src[i] >> 20) & 0xF] << 20); \
+glyphBuffer->pixelRows[i] |= val << shiftAmount->left; \
+glyphBuffer->pixelRows[i + 8] |= val >> shiftAmount->right; \
+
+static void ShiftGlyphTile_ShadowedFont_Width6(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u32 val;
+ SHIFT_GLYPH_WIDTH6_STEP(0)
+ SHIFT_GLYPH_WIDTH6_STEP(1)
+ SHIFT_GLYPH_WIDTH6_STEP(2)
+ SHIFT_GLYPH_WIDTH6_STEP(3)
+ SHIFT_GLYPH_WIDTH6_STEP(4)
+ SHIFT_GLYPH_WIDTH6_STEP(5)
+ SHIFT_GLYPH_WIDTH6_STEP(6)
+ SHIFT_GLYPH_WIDTH6_STEP(7)
+}
+
+#define SHIFT_GLYPH_WIDTH7_STEP(i) \
+val = (colors[(src[i] >> 0) & 0xF] << 0) \
+ | (colors[(src[i] >> 4) & 0xF] << 4) \
+ | (colors[(src[i] >> 8) & 0xF] << 8) \
+ | (colors[(src[i] >> 12) & 0xF] << 12) \
+ | (colors[(src[i] >> 16) & 0xF] << 16) \
+ | (colors[(src[i] >> 20) & 0xF] << 20) \
+ | (colors[(src[i] >> 24) & 0xF] << 24); \
+glyphBuffer->pixelRows[i] |= val << shiftAmount->left; \
+glyphBuffer->pixelRows[i + 8] |= val >> shiftAmount->right; \
+
+static void ShiftGlyphTile_ShadowedFont_Width7(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u32 val;
+ SHIFT_GLYPH_WIDTH7_STEP(0)
+ SHIFT_GLYPH_WIDTH7_STEP(1)
+ SHIFT_GLYPH_WIDTH7_STEP(2)
+ SHIFT_GLYPH_WIDTH7_STEP(3)
+ SHIFT_GLYPH_WIDTH7_STEP(4)
+ SHIFT_GLYPH_WIDTH7_STEP(5)
+ SHIFT_GLYPH_WIDTH7_STEP(6)
+ SHIFT_GLYPH_WIDTH7_STEP(7)
+}
+
+#define SHIFT_GLYPH_WIDTH8_STEP(i) \
+val = (colors[(src[i] >> 0) & 0xF] << 0) \
+ | (colors[(src[i] >> 4) & 0xF] << 4) \
+ | (colors[(src[i] >> 8) & 0xF] << 8) \
+ | (colors[(src[i] >> 12) & 0xF] << 12) \
+ | (colors[(src[i] >> 16) & 0xF] << 16) \
+ | (colors[(src[i] >> 20) & 0xF] << 20) \
+ | (colors[(src[i] >> 24) & 0xF] << 24) \
+ | (colors[(src[i] >> 28) ] << 28); \
+glyphBuffer->pixelRows[i] |= val << shiftAmount->left; \
+glyphBuffer->pixelRows[i + 8] |= val >> shiftAmount->right; \
+
+static void ShiftGlyphTile_ShadowedFont_Width8(struct GlyphBuffer *glyphBuffer, u32 *src, u32 *colors, u8 startPixel)
+{
+ const struct ShiftAmount *shiftAmount = &sGlyphShiftAmounts[startPixel];
+ u32 val;
+ SHIFT_GLYPH_WIDTH8_STEP(0)
+ SHIFT_GLYPH_WIDTH8_STEP(1)
+ SHIFT_GLYPH_WIDTH8_STEP(2)
+ SHIFT_GLYPH_WIDTH8_STEP(3)
+ SHIFT_GLYPH_WIDTH8_STEP(4)
+ SHIFT_GLYPH_WIDTH8_STEP(5)
+ SHIFT_GLYPH_WIDTH8_STEP(6)
+ SHIFT_GLYPH_WIDTH8_STEP(7)
+}
+
+static s32 DrawGlyphTiles(struct Window *win, u32 glyph, u32 glyphWidth)
+{
+ struct GlyphTileInfo glyphTileInfo;
+ u8 *upperTile;
+ u8 *lowerTile;
+ s32 retVal = 0;
+
+ GetGlyphTilePointers(win->fontNum, win->language, glyph, &upperTile, &lowerTile);
+ glyphTileInfo.textMode = win->textMode;
+ glyphTileInfo.startPixel = (win->left + win->cursorX) & 7;
+ glyphTileInfo.width = glyphWidth;
+ glyphTileInfo.src = upperTile;
+ glyphTileInfo.dest = (u32 *)(win->tileData + 32 * GetCursorTileNum(win, 0, 0));
+ glyphTileInfo.colors = sGlyphBuffer.colors;
+
+ switch (win->fontNum)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 6:
+ DrawGlyphTile_UnshadowedFont(&glyphTileInfo);
+ glyphTileInfo.src = lowerTile;
+ glyphTileInfo.dest = (u32 *)(win->tileData + 32 * GetCursorTileNum(win, 0, 1));
+ retVal = DrawGlyphTile_UnshadowedFont(&glyphTileInfo);
+ break;
+ case 3:
+ case 4:
+ case 5:
+ DrawGlyphTile_ShadowedFont(&glyphTileInfo);
+ glyphTileInfo.src = lowerTile;
+ glyphTileInfo.dest = (u32 *)(win->tileData + 32 * GetCursorTileNum(win, 0, 1));
+ retVal = DrawGlyphTile_ShadowedFont(&glyphTileInfo);
+ break;
+ }
+
+ return retVal;
+}
+
+static void UpdateTilemap(struct Window *win, u32 tilesWidth)
+{
+ u16 *tilemap = GetCursorTilemapPointer(win);
+ if (tilesWidth && tilemap)
+ {
+ u16 paletteNum = (win->paletteNum << 12);
+ u16 upperLeftTileNum = GetCursorTileNum(win, 0, 0);
+ u16 lowerLeftTileNum = GetCursorTileNum(win, 0, 1);
+ tilemap[0] = upperLeftTileNum | paletteNum;
+ tilemap[32] = lowerLeftTileNum | paletteNum;
+ if (tilesWidth == 2)
+ {
+ u16 upperRightTileNum = GetCursorTileNum(win, 1, 0);
+ u16 lowerRightTileNum = GetCursorTileNum(win, 1, 1);
+ tilemap[1] = upperRightTileNum | paletteNum;
+ tilemap[33] = lowerRightTileNum | paletteNum;
+ }
+ }
+}
+
+static u16 GetCursorTileNum(struct Window *win, u32 xOffset, u32 yOffset)
+{
+ u16 index;
+
+ if (win->textMode == 2)
+ index = win->tileDataStartOffset
+ + win->tileDataOffset
+ + (((win->top + win->cursorY) >> 3) + yOffset) * win->width
+ + (((win->left + win->cursorX) >> 3) + xOffset);
+ else
+ index = win->tileDataStartOffset + win->tileDataOffset + 2 * xOffset + yOffset;
+
+ return index;
+}