mirror of
https://github.com/pret/pokefirered.git
synced 2026-09-29 20:38:15 -05:00
merge text_printer.c into text.c
This commit is contained in:
301
gflib/text.c
301
gflib/text.c
@@ -42,8 +42,38 @@ static u32 GetGlyphWidth_SmallNarrower(u16, bool32);
|
||||
static u32 GetGlyphWidth_ShortNarrow(u16, bool32);
|
||||
static void SpriteCB_TextCursor(struct Sprite *sprite);
|
||||
|
||||
static EWRAM_DATA struct TextPrinter sTempTextPrinter = {0};
|
||||
static EWRAM_DATA struct TextPrinter sTextPrinters[NUM_TEXT_PRINTERS] = {0};
|
||||
|
||||
static u16 sFontHalfRowLookupTable[0x51];
|
||||
static u16 sLastTextBgColor;
|
||||
static u16 sLastTextFgColor;
|
||||
static u16 sLastTextShadowColor;
|
||||
|
||||
const struct FontInfo *gFonts;
|
||||
struct GlyphInfo gGlyphInfo;
|
||||
TextFlags gTextFlags;
|
||||
|
||||
static const u8 sFontHalfRowOffsets[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
|
||||
0x09, 0x0A, 0x0B, 0x09, 0x0C, 0x0D, 0x0E, 0x0C, 0x0F, 0x10, 0x11, 0x0F, 0x09, 0x0A, 0x0B, 0x09,
|
||||
0x12, 0x13, 0x14, 0x12, 0x15, 0x16, 0x17, 0x15, 0x18, 0x19, 0x1A, 0x18, 0x12, 0x13, 0x14, 0x12,
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
|
||||
0x1B, 0x1C, 0x1D, 0x1B, 0x1E, 0x1F, 0x20, 0x1E, 0x21, 0x22, 0x23, 0x21, 0x1B, 0x1C, 0x1D, 0x1B,
|
||||
0x24, 0x25, 0x26, 0x24, 0x27, 0x28, 0x29, 0x27, 0x2A, 0x2B, 0x2C, 0x2A, 0x24, 0x25, 0x26, 0x24,
|
||||
0x2D, 0x2E, 0x2F, 0x2D, 0x30, 0x31, 0x32, 0x30, 0x33, 0x34, 0x35, 0x33, 0x2D, 0x2E, 0x2F, 0x2D,
|
||||
0x1B, 0x1C, 0x1D, 0x1B, 0x1E, 0x1F, 0x20, 0x1E, 0x21, 0x22, 0x23, 0x21, 0x1B, 0x1C, 0x1D, 0x1B,
|
||||
0x36, 0x37, 0x38, 0x36, 0x39, 0x3A, 0x3B, 0x39, 0x3C, 0x3D, 0x3E, 0x3C, 0x36, 0x37, 0x38, 0x36,
|
||||
0x3F, 0x40, 0x41, 0x3F, 0x42, 0x43, 0x44, 0x42, 0x45, 0x46, 0x47, 0x45, 0x3F, 0x40, 0x41, 0x3F,
|
||||
0x48, 0x49, 0x4A, 0x48, 0x4B, 0x4C, 0x4D, 0x4B, 0x4E, 0x4F, 0x50, 0x4E, 0x48, 0x49, 0x4A, 0x48,
|
||||
0x36, 0x37, 0x38, 0x36, 0x39, 0x3A, 0x3B, 0x39, 0x3C, 0x3D, 0x3E, 0x3C, 0x36, 0x37, 0x38, 0x36,
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
|
||||
0x09, 0x0A, 0x0B, 0x09, 0x0C, 0x0D, 0x0E, 0x0C, 0x0F, 0x10, 0x11, 0x0F, 0x09, 0x0A, 0x0B, 0x09,
|
||||
0x12, 0x13, 0x14, 0x12, 0x15, 0x16, 0x17, 0x15, 0x18, 0x19, 0x1A, 0x18, 0x12, 0x13, 0x14, 0x12,
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00
|
||||
};
|
||||
|
||||
static const u8 sDownArrowTiles[] = INCBIN_U8("graphics/fonts/down_arrow.4bpp");
|
||||
static const u8 sDarkDownArrowTiles[] = INCBIN_U8("graphics/fonts/down_arrow_RS.4bpp");
|
||||
static const u8 sTinyArrowTiles[] = INCBIN_U8("graphics/fonts/down_arrow_2.4bpp");
|
||||
@@ -588,6 +618,277 @@ ALIGNED(4) const u8 gFontShortNarrowLatinGlyphWidths[] = {
|
||||
|
||||
static const u16 sFontBoldJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/japanese_bold.fwjpnfont");
|
||||
|
||||
void SetFontsPointer(const struct FontInfo *fonts)
|
||||
{
|
||||
gFonts = fonts;
|
||||
}
|
||||
|
||||
void DeactivateAllTextPrinters (void)
|
||||
{
|
||||
int printer;
|
||||
for (printer = 0; printer < NUM_TEXT_PRINTERS; ++printer)
|
||||
sTextPrinters[printer].active = 0;
|
||||
}
|
||||
|
||||
u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
|
||||
{
|
||||
struct TextPrinterTemplate printerTemplate;
|
||||
|
||||
printerTemplate.currentChar = str;
|
||||
printerTemplate.windowId = windowId;
|
||||
printerTemplate.fontId = fontId;
|
||||
printerTemplate.x = x;
|
||||
printerTemplate.y = y;
|
||||
printerTemplate.currentX = x;
|
||||
printerTemplate.currentY = y;
|
||||
printerTemplate.letterSpacing = gFonts[fontId].letterSpacing;
|
||||
printerTemplate.lineSpacing = gFonts[fontId].lineSpacing;
|
||||
printerTemplate.unk = gFonts[fontId].unk;
|
||||
printerTemplate.fgColor = gFonts[fontId].fgColor;
|
||||
printerTemplate.bgColor = gFonts[fontId].bgColor;
|
||||
printerTemplate.shadowColor = gFonts[fontId].shadowColor;
|
||||
return AddTextPrinter(&printerTemplate, speed, callback);
|
||||
}
|
||||
|
||||
bool16 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
|
||||
{
|
||||
int i;
|
||||
u16 j;
|
||||
|
||||
if (!gFonts)
|
||||
return FALSE;
|
||||
|
||||
sTempTextPrinter.active = TRUE;
|
||||
sTempTextPrinter.state = RENDER_STATE_HANDLE_CHAR;
|
||||
sTempTextPrinter.textSpeed = speed;
|
||||
sTempTextPrinter.delayCounter = 0;
|
||||
sTempTextPrinter.scrollDistance = 0;
|
||||
|
||||
for (i = 0; i < (int)ARRAY_COUNT(sTempTextPrinter.subUnion.fields); ++i)
|
||||
sTempTextPrinter.subUnion.fields[i] = 0;
|
||||
|
||||
sTempTextPrinter.printerTemplate = *textSubPrinter;
|
||||
sTempTextPrinter.callback = callback;
|
||||
sTempTextPrinter.minLetterSpacing = 0;
|
||||
sTempTextPrinter.japanese = 0;
|
||||
|
||||
GenerateFontHalfRowLookupTable(textSubPrinter->fgColor, textSubPrinter->bgColor, textSubPrinter->shadowColor);
|
||||
if (speed != TEXT_SKIP_DRAW && speed != 0)
|
||||
{
|
||||
--sTempTextPrinter.textSpeed;
|
||||
sTextPrinters[textSubPrinter->windowId] = sTempTextPrinter;
|
||||
}
|
||||
else
|
||||
{
|
||||
sTempTextPrinter.textSpeed = 0;
|
||||
|
||||
// Render all text (up to limit) at once
|
||||
for (j = 0; j < 0x400; ++j)
|
||||
{
|
||||
if (RenderFont(&sTempTextPrinter) == RENDER_FINISH)
|
||||
break;
|
||||
}
|
||||
|
||||
// All the text is rendered to the window but don't draw it yet.
|
||||
if (speed != TEXT_SKIP_DRAW)
|
||||
CopyWindowToVram(sTempTextPrinter.printerTemplate.windowId, COPYWIN_GFX);
|
||||
sTextPrinters[textSubPrinter->windowId].active = FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RunTextPrinters(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_TEXT_PRINTERS; ++i)
|
||||
{
|
||||
if (sTextPrinters[i].active)
|
||||
{
|
||||
u16 renderCmd = RenderFont(&sTextPrinters[i]);
|
||||
switch (renderCmd)
|
||||
{
|
||||
case RENDER_PRINT:
|
||||
CopyWindowToVram(sTextPrinters[i].printerTemplate.windowId, COPYWIN_GFX);
|
||||
case RENDER_UPDATE:
|
||||
if (sTextPrinters[i].callback != NULL)
|
||||
sTextPrinters[i].callback(&sTextPrinters[i].printerTemplate, renderCmd);
|
||||
break;
|
||||
case RENDER_FINISH:
|
||||
sTextPrinters[i].active = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor)
|
||||
{
|
||||
int lutIndex;
|
||||
int i, j, k, l;
|
||||
const u32 colors[] = {bgColor, fgColor, shadowColor};
|
||||
|
||||
sLastTextBgColor = bgColor;
|
||||
sLastTextFgColor = fgColor;
|
||||
sLastTextShadowColor = shadowColor;
|
||||
|
||||
lutIndex = 0;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
for (k = 0; k < 3; k++)
|
||||
for (l = 0; l < 3; l++)
|
||||
sFontHalfRowLookupTable[lutIndex++] = (colors[l] << 12) | (colors[k] << 8) | (colors[j] << 4) | colors[i];
|
||||
}
|
||||
|
||||
bool16 IsTextPrinterActive(u8 id)
|
||||
{
|
||||
return sTextPrinters[id].active;
|
||||
}
|
||||
|
||||
u32 RenderFont(struct TextPrinter *textPrinter)
|
||||
{
|
||||
u32 ret;
|
||||
while (TRUE)
|
||||
{
|
||||
ret = gFonts[textPrinter->printerTemplate.fontId].fontFunction(textPrinter);
|
||||
if (ret != 2)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTextColors(u8 *fgColor, u8 *bgColor, u8 *shadowColor)
|
||||
{
|
||||
*bgColor = sLastTextBgColor;
|
||||
*fgColor = sLastTextFgColor;
|
||||
*shadowColor = sLastTextShadowColor;
|
||||
}
|
||||
|
||||
void RestoreTextColors(u8 *fgColor, u8 *bgColor, u8 *shadowColor)
|
||||
{
|
||||
GenerateFontHalfRowLookupTable(*fgColor, *bgColor, *shadowColor);
|
||||
}
|
||||
|
||||
void DecompressGlyphTile(const u16 *src, u16 *dest)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
int offsetIndex = (i << 31) != 0 ? (u8)*src++ : (*src >> 8);
|
||||
dest[i] = sFontHalfRowLookupTable[sFontHalfRowOffsets[offsetIndex]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u8 GetLastTextColor(u8 colorType)
|
||||
{
|
||||
switch (colorType)
|
||||
{
|
||||
case 0:
|
||||
return sLastTextFgColor;
|
||||
case 2:
|
||||
return sLastTextBgColor;
|
||||
case 1:
|
||||
return sLastTextShadowColor;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define GLYPH_COPY(widthOffset, heightOffset, width, height, tilesDest, left, top, sizeX) \
|
||||
{ \
|
||||
int xAdd, xpos, yAdd, ypos, toOrr, bits; \
|
||||
u8 * src, * dst; \
|
||||
u32 _8pixbuf; \
|
||||
\
|
||||
src = gGlyphInfo.pixels + (heightOffset / 8 * 0x40) + (widthOffset / 8 * 0x20); \
|
||||
for (yAdd = 0, ypos = top + heightOffset; yAdd < height; yAdd++, ypos++) \
|
||||
{ \
|
||||
_8pixbuf = *(u32 *)src; \
|
||||
for (xAdd = 0, xpos = left + widthOffset; xAdd < width; xAdd++, xpos++) \
|
||||
{ \
|
||||
dst = (u8 *)((tilesDest) + ((xpos >> 1) & 3) + ((xpos >> 3) << 5) + (((ypos >> 3) * (sizeX)) << 5) + ((u32)(ypos << 29) >> 27)); \
|
||||
toOrr = (_8pixbuf >> (xAdd * 4)) & 0xF; \
|
||||
if (toOrr != 0) \
|
||||
{ \
|
||||
bits = (xpos & 1) * 4; \
|
||||
*dst = (toOrr << bits) | (*dst & (0xF0 >> bits)); \
|
||||
} \
|
||||
} \
|
||||
src += 4; \
|
||||
} \
|
||||
}
|
||||
|
||||
void CopyGlyphToWindow(struct TextPrinter *textPrinter)
|
||||
{
|
||||
int glyphWidth, glyphHeight;
|
||||
u8 sizeType;
|
||||
|
||||
if (gWindows[textPrinter->printerTemplate.windowId].window.width * 8 - textPrinter->printerTemplate.currentX < gGlyphInfo.width)
|
||||
glyphWidth = gWindows[textPrinter->printerTemplate.windowId].window.width * 8 - textPrinter->printerTemplate.currentX;
|
||||
else
|
||||
glyphWidth = gGlyphInfo.width;
|
||||
if (gWindows[textPrinter->printerTemplate.windowId].window.height * 8 - textPrinter->printerTemplate.currentY < gGlyphInfo.height)
|
||||
glyphHeight = gWindows[textPrinter->printerTemplate.windowId].window.height * 8 - textPrinter->printerTemplate.currentY;
|
||||
else
|
||||
glyphHeight = gGlyphInfo.height;
|
||||
|
||||
sizeType = 0;
|
||||
if (glyphWidth > 8)
|
||||
sizeType |= 1;
|
||||
if (glyphHeight > 8)
|
||||
sizeType |= 2;
|
||||
|
||||
switch (sizeType)
|
||||
{
|
||||
case 0: // ≤ 8x8
|
||||
GLYPH_COPY(0, 0, glyphWidth, glyphHeight, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
case 1: // ≤ 16x8
|
||||
GLYPH_COPY(0, 0, 8, glyphHeight, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(8, 0, glyphWidth - 8, glyphHeight, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
case 2: // ≤ 8x16
|
||||
GLYPH_COPY(0, 0, glyphWidth, 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(0, 8, glyphWidth, glyphHeight - 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
case 3: // ≤ 16x16
|
||||
GLYPH_COPY(0, 0, 8, 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(8, 0, glyphWidth - 8, 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(0, 8, 8, glyphHeight - 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(8, 8, glyphWidth - 8, glyphHeight - 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearTextSpan(struct TextPrinter *textPrinter, u32 width)
|
||||
{
|
||||
struct Window *window;
|
||||
struct Bitmap pixels_data;
|
||||
struct GlyphInfo *glyph;
|
||||
u8 *glyphHeight;
|
||||
|
||||
if (sLastTextBgColor != TEXT_COLOR_TRANSPARENT)
|
||||
{
|
||||
window = &gWindows[textPrinter->printerTemplate.windowId];
|
||||
pixels_data.pixels = window->tileData;
|
||||
pixels_data.width = window->window.width << 3;
|
||||
pixels_data.height = window->window.height << 3;
|
||||
|
||||
glyph = &gGlyphInfo;
|
||||
glyphHeight = &glyph->height;
|
||||
|
||||
FillBitmapRect4Bit(
|
||||
&pixels_data,
|
||||
textPrinter->printerTemplate.currentX,
|
||||
textPrinter->printerTemplate.currentY,
|
||||
width,
|
||||
*glyphHeight,
|
||||
sLastTextBgColor);
|
||||
}
|
||||
}
|
||||
|
||||
u16 FontFunc_Small(struct TextPrinter *textPrinter)
|
||||
{
|
||||
struct TextPrinterSubStruct *subStruct = &textPrinter->subUnion.sub;
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "blit.h"
|
||||
#include "window.h"
|
||||
#include "text.h"
|
||||
|
||||
static EWRAM_DATA struct TextPrinter sTempTextPrinter = {0};
|
||||
static EWRAM_DATA struct TextPrinter sTextPrinters[NUM_TEXT_PRINTERS] = {0};
|
||||
|
||||
static u16 sFontHalfRowLookupTable[0x51];
|
||||
static u16 sLastTextBgColor;
|
||||
static u16 sLastTextFgColor;
|
||||
static u16 sLastTextShadowColor;
|
||||
|
||||
const struct FontInfo *gFonts;
|
||||
struct GlyphInfo gGlyphInfo;
|
||||
|
||||
static const u8 sFontHalfRowOffsets[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
|
||||
0x09, 0x0A, 0x0B, 0x09, 0x0C, 0x0D, 0x0E, 0x0C, 0x0F, 0x10, 0x11, 0x0F, 0x09, 0x0A, 0x0B, 0x09,
|
||||
0x12, 0x13, 0x14, 0x12, 0x15, 0x16, 0x17, 0x15, 0x18, 0x19, 0x1A, 0x18, 0x12, 0x13, 0x14, 0x12,
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
|
||||
0x1B, 0x1C, 0x1D, 0x1B, 0x1E, 0x1F, 0x20, 0x1E, 0x21, 0x22, 0x23, 0x21, 0x1B, 0x1C, 0x1D, 0x1B,
|
||||
0x24, 0x25, 0x26, 0x24, 0x27, 0x28, 0x29, 0x27, 0x2A, 0x2B, 0x2C, 0x2A, 0x24, 0x25, 0x26, 0x24,
|
||||
0x2D, 0x2E, 0x2F, 0x2D, 0x30, 0x31, 0x32, 0x30, 0x33, 0x34, 0x35, 0x33, 0x2D, 0x2E, 0x2F, 0x2D,
|
||||
0x1B, 0x1C, 0x1D, 0x1B, 0x1E, 0x1F, 0x20, 0x1E, 0x21, 0x22, 0x23, 0x21, 0x1B, 0x1C, 0x1D, 0x1B,
|
||||
0x36, 0x37, 0x38, 0x36, 0x39, 0x3A, 0x3B, 0x39, 0x3C, 0x3D, 0x3E, 0x3C, 0x36, 0x37, 0x38, 0x36,
|
||||
0x3F, 0x40, 0x41, 0x3F, 0x42, 0x43, 0x44, 0x42, 0x45, 0x46, 0x47, 0x45, 0x3F, 0x40, 0x41, 0x3F,
|
||||
0x48, 0x49, 0x4A, 0x48, 0x4B, 0x4C, 0x4D, 0x4B, 0x4E, 0x4F, 0x50, 0x4E, 0x48, 0x49, 0x4A, 0x48,
|
||||
0x36, 0x37, 0x38, 0x36, 0x39, 0x3A, 0x3B, 0x39, 0x3C, 0x3D, 0x3E, 0x3C, 0x36, 0x37, 0x38, 0x36,
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
|
||||
0x09, 0x0A, 0x0B, 0x09, 0x0C, 0x0D, 0x0E, 0x0C, 0x0F, 0x10, 0x11, 0x0F, 0x09, 0x0A, 0x0B, 0x09,
|
||||
0x12, 0x13, 0x14, 0x12, 0x15, 0x16, 0x17, 0x15, 0x18, 0x19, 0x1A, 0x18, 0x12, 0x13, 0x14, 0x12,
|
||||
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00
|
||||
};
|
||||
|
||||
void SetFontsPointer(const struct FontInfo *fonts)
|
||||
{
|
||||
gFonts = fonts;
|
||||
}
|
||||
|
||||
void DeactivateAllTextPrinters (void)
|
||||
{
|
||||
int printer;
|
||||
for (printer = 0; printer < NUM_TEXT_PRINTERS; ++printer)
|
||||
sTextPrinters[printer].active = 0;
|
||||
}
|
||||
|
||||
u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
|
||||
{
|
||||
struct TextPrinterTemplate printerTemplate;
|
||||
|
||||
printerTemplate.currentChar = str;
|
||||
printerTemplate.windowId = windowId;
|
||||
printerTemplate.fontId = fontId;
|
||||
printerTemplate.x = x;
|
||||
printerTemplate.y = y;
|
||||
printerTemplate.currentX = x;
|
||||
printerTemplate.currentY = y;
|
||||
printerTemplate.letterSpacing = gFonts[fontId].letterSpacing;
|
||||
printerTemplate.lineSpacing = gFonts[fontId].lineSpacing;
|
||||
printerTemplate.unk = gFonts[fontId].unk;
|
||||
printerTemplate.fgColor = gFonts[fontId].fgColor;
|
||||
printerTemplate.bgColor = gFonts[fontId].bgColor;
|
||||
printerTemplate.shadowColor = gFonts[fontId].shadowColor;
|
||||
return AddTextPrinter(&printerTemplate, speed, callback);
|
||||
}
|
||||
|
||||
bool16 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
|
||||
{
|
||||
int i;
|
||||
u16 j;
|
||||
|
||||
if (!gFonts)
|
||||
return FALSE;
|
||||
|
||||
sTempTextPrinter.active = TRUE;
|
||||
sTempTextPrinter.state = RENDER_STATE_HANDLE_CHAR;
|
||||
sTempTextPrinter.textSpeed = speed;
|
||||
sTempTextPrinter.delayCounter = 0;
|
||||
sTempTextPrinter.scrollDistance = 0;
|
||||
|
||||
for (i = 0; i < (int)ARRAY_COUNT(sTempTextPrinter.subUnion.fields); ++i)
|
||||
sTempTextPrinter.subUnion.fields[i] = 0;
|
||||
|
||||
sTempTextPrinter.printerTemplate = *textSubPrinter;
|
||||
sTempTextPrinter.callback = callback;
|
||||
sTempTextPrinter.minLetterSpacing = 0;
|
||||
sTempTextPrinter.japanese = 0;
|
||||
|
||||
GenerateFontHalfRowLookupTable(textSubPrinter->fgColor, textSubPrinter->bgColor, textSubPrinter->shadowColor);
|
||||
if (speed != TEXT_SKIP_DRAW && speed != 0)
|
||||
{
|
||||
--sTempTextPrinter.textSpeed;
|
||||
sTextPrinters[textSubPrinter->windowId] = sTempTextPrinter;
|
||||
}
|
||||
else
|
||||
{
|
||||
sTempTextPrinter.textSpeed = 0;
|
||||
|
||||
// Render all text (up to limit) at once
|
||||
for (j = 0; j < 0x400; ++j)
|
||||
{
|
||||
if (RenderFont(&sTempTextPrinter) == RENDER_FINISH)
|
||||
break;
|
||||
}
|
||||
|
||||
// All the text is rendered to the window but don't draw it yet.
|
||||
if (speed != TEXT_SKIP_DRAW)
|
||||
CopyWindowToVram(sTempTextPrinter.printerTemplate.windowId, COPYWIN_GFX);
|
||||
sTextPrinters[textSubPrinter->windowId].active = FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RunTextPrinters(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_TEXT_PRINTERS; ++i)
|
||||
{
|
||||
if (sTextPrinters[i].active)
|
||||
{
|
||||
u16 renderCmd = RenderFont(&sTextPrinters[i]);
|
||||
switch (renderCmd)
|
||||
{
|
||||
case RENDER_PRINT:
|
||||
CopyWindowToVram(sTextPrinters[i].printerTemplate.windowId, COPYWIN_GFX);
|
||||
case RENDER_UPDATE:
|
||||
if (sTextPrinters[i].callback != NULL)
|
||||
sTextPrinters[i].callback(&sTextPrinters[i].printerTemplate, renderCmd);
|
||||
break;
|
||||
case RENDER_FINISH:
|
||||
sTextPrinters[i].active = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool16 IsTextPrinterActive(u8 id)
|
||||
{
|
||||
return sTextPrinters[id].active;
|
||||
}
|
||||
|
||||
u32 RenderFont(struct TextPrinter *textPrinter)
|
||||
{
|
||||
u32 ret;
|
||||
while (TRUE)
|
||||
{
|
||||
ret = gFonts[textPrinter->printerTemplate.fontId].fontFunction(textPrinter);
|
||||
if (ret != 2)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor)
|
||||
{
|
||||
int lutIndex;
|
||||
int i, j, k, l;
|
||||
const u32 colors[] = {bgColor, fgColor, shadowColor};
|
||||
|
||||
sLastTextBgColor = bgColor;
|
||||
sLastTextFgColor = fgColor;
|
||||
sLastTextShadowColor = shadowColor;
|
||||
|
||||
lutIndex = 0;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
for (k = 0; k < 3; k++)
|
||||
for (l = 0; l < 3; l++)
|
||||
sFontHalfRowLookupTable[lutIndex++] = (colors[l] << 12) | (colors[k] << 8) | (colors[j] << 4) | colors[i];
|
||||
}
|
||||
|
||||
void SaveTextColors(u8 *fgColor, u8 *bgColor, u8 *shadowColor)
|
||||
{
|
||||
*bgColor = sLastTextBgColor;
|
||||
*fgColor = sLastTextFgColor;
|
||||
*shadowColor = sLastTextShadowColor;
|
||||
}
|
||||
|
||||
void RestoreTextColors(u8 *fgColor, u8 *bgColor, u8 *shadowColor)
|
||||
{
|
||||
GenerateFontHalfRowLookupTable(*fgColor, *bgColor, *shadowColor);
|
||||
}
|
||||
|
||||
void DecompressGlyphTile(const u16 *src, u16 *dest)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
int offsetIndex = (i << 31) != 0 ? (u8)*src++ : (*src >> 8);
|
||||
dest[i] = sFontHalfRowLookupTable[sFontHalfRowOffsets[offsetIndex]];
|
||||
}
|
||||
}
|
||||
|
||||
u8 GetLastTextColor(u8 colorType)
|
||||
{
|
||||
switch (colorType)
|
||||
{
|
||||
case 0:
|
||||
return sLastTextFgColor;
|
||||
case 2:
|
||||
return sLastTextBgColor;
|
||||
case 1:
|
||||
return sLastTextShadowColor;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define GLYPH_COPY(widthOffset, heightOffset, width, height, tilesDest, left, top, sizeX) \
|
||||
{ \
|
||||
int xAdd, xpos, yAdd, ypos, toOrr, bits; \
|
||||
u8 * src, * dst; \
|
||||
u32 _8pixbuf; \
|
||||
\
|
||||
src = gGlyphInfo.pixels + (heightOffset / 8 * 0x40) + (widthOffset / 8 * 0x20); \
|
||||
for (yAdd = 0, ypos = top + heightOffset; yAdd < height; yAdd++, ypos++) \
|
||||
{ \
|
||||
_8pixbuf = *(u32 *)src; \
|
||||
for (xAdd = 0, xpos = left + widthOffset; xAdd < width; xAdd++, xpos++) \
|
||||
{ \
|
||||
dst = (u8 *)((tilesDest) + ((xpos >> 1) & 3) + ((xpos >> 3) << 5) + (((ypos >> 3) * (sizeX)) << 5) + ((u32)(ypos << 29) >> 27)); \
|
||||
toOrr = (_8pixbuf >> (xAdd * 4)) & 0xF; \
|
||||
if (toOrr != 0) \
|
||||
{ \
|
||||
bits = (xpos & 1) * 4; \
|
||||
*dst = (toOrr << bits) | (*dst & (0xF0 >> bits)); \
|
||||
} \
|
||||
} \
|
||||
src += 4; \
|
||||
} \
|
||||
}
|
||||
|
||||
void CopyGlyphToWindow(struct TextPrinter *textPrinter)
|
||||
{
|
||||
int glyphWidth, glyphHeight;
|
||||
u8 sizeType;
|
||||
|
||||
if (gWindows[textPrinter->printerTemplate.windowId].window.width * 8 - textPrinter->printerTemplate.currentX < gGlyphInfo.width)
|
||||
glyphWidth = gWindows[textPrinter->printerTemplate.windowId].window.width * 8 - textPrinter->printerTemplate.currentX;
|
||||
else
|
||||
glyphWidth = gGlyphInfo.width;
|
||||
if (gWindows[textPrinter->printerTemplate.windowId].window.height * 8 - textPrinter->printerTemplate.currentY < gGlyphInfo.height)
|
||||
glyphHeight = gWindows[textPrinter->printerTemplate.windowId].window.height * 8 - textPrinter->printerTemplate.currentY;
|
||||
else
|
||||
glyphHeight = gGlyphInfo.height;
|
||||
|
||||
sizeType = 0;
|
||||
if (glyphWidth > 8)
|
||||
sizeType |= 1;
|
||||
if (glyphHeight > 8)
|
||||
sizeType |= 2;
|
||||
|
||||
switch (sizeType)
|
||||
{
|
||||
case 0: // ≤ 8x8
|
||||
GLYPH_COPY(0, 0, glyphWidth, glyphHeight, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
case 1: // ≤ 16x8
|
||||
GLYPH_COPY(0, 0, 8, glyphHeight, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(8, 0, glyphWidth - 8, glyphHeight, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
case 2: // ≤ 8x16
|
||||
GLYPH_COPY(0, 0, glyphWidth, 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(0, 8, glyphWidth, glyphHeight - 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
case 3: // ≤ 16x16
|
||||
GLYPH_COPY(0, 0, 8, 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(8, 0, glyphWidth - 8, 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(0, 8, 8, glyphHeight - 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
GLYPH_COPY(8, 8, glyphWidth - 8, glyphHeight - 8, gWindows[textPrinter->printerTemplate.windowId].tileData, textPrinter->printerTemplate.currentX, textPrinter->printerTemplate.currentY, ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8 + ((gWindows[textPrinter->printerTemplate.windowId].window.width * 8) & 7)) >> 3));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearTextSpan(struct TextPrinter *textPrinter, u32 width)
|
||||
{
|
||||
struct Window *window;
|
||||
struct Bitmap pixels_data;
|
||||
struct GlyphInfo *glyph;
|
||||
u8 *glyphHeight;
|
||||
|
||||
if (sLastTextBgColor != TEXT_COLOR_TRANSPARENT)
|
||||
{
|
||||
window = &gWindows[textPrinter->printerTemplate.windowId];
|
||||
pixels_data.pixels = window->tileData;
|
||||
pixels_data.width = window->window.width << 3;
|
||||
pixels_data.height = window->window.height << 3;
|
||||
|
||||
glyph = &gGlyphInfo;
|
||||
glyphHeight = &glyph->height;
|
||||
|
||||
FillBitmapRect4Bit(
|
||||
&pixels_data,
|
||||
textPrinter->printerTemplate.currentX,
|
||||
textPrinter->printerTemplate.currentY,
|
||||
width,
|
||||
*glyphHeight,
|
||||
sLastTextBgColor);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user