#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[] = { ®_BG0CNT, ®_BG1CNT, ®_BG2CNT, ®_BG3CNT, }; vu16 *const gBGHOffsetRegs[] = { ®_BG0HOFS, ®_BG1HOFS, ®_BG2HOFS, ®_BG3HOFS, }; vu16 *const gBGVOffsetRegs[] = { ®_BG0VOFS, ®_BG1VOFS, ®_BG2VOFS, ®_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 }; #include "fonts/font0_lat_glyphs.h" #include "fonts/font1_lat_glyphs.h" #include "fonts/font0_jpn_glyphs.h" #include "fonts/font1_jpn_glyphs.h" #include "fonts/braille_glyphs.h" #include "fonts/down_arrow_tiles.h" #include "fonts/type1_map.h" #include "fonts/type3_map.h" #include "fonts/font1_widths.h" #include "fonts/font4_widths.h" #include "fonts/font0_widths.h" #include "fonts/font3_widths.h" #include "fonts/unknown_palette_81E6692.h" #include "fonts/default_palette.h" 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, 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; } u8 sub_800374C(struct Window *win) { u8 retVal; sWaitType = 1; sLineLength = 26; 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; }