From 376c3e715e1b849077febe956aa954be53fad810 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 28 Jul 2016 00:32:00 -0700 Subject: [PATCH] 3DS: Use system font for menus --- CHANGES | 1 + src/platform/3ds/CMakeLists.txt | 6 ---- src/platform/3ds/ctr-gpu.c | 53 ++++++++++++++++------------ src/platform/3ds/font.raw | Bin 65536 -> 0 bytes src/platform/3ds/gui-font.c | 59 +++++++++++++++++++------------- src/platform/3ds/main.c | 2 ++ 6 files changed, 70 insertions(+), 51 deletions(-) delete mode 100644 src/platform/3ds/font.raw diff --git a/CHANGES b/CHANGES index 73c0e813c..e45502fb0 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,7 @@ Misc: - GBA Audio: Force audio DMAs to not increment destination - Qt: Thread startup improvements - 3DS: Port to using citro3D + - 3DS: Use system font for menus 0.4.1: (2016-07-11) Bugfixes: diff --git a/src/platform/3ds/CMakeLists.txt b/src/platform/3ds/CMakeLists.txt index cc6ebbf37..942a8517c 100644 --- a/src/platform/3ds/CMakeLists.txt +++ b/src/platform/3ds/CMakeLists.txt @@ -30,7 +30,6 @@ set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) list(APPEND GUI_SRC ${CMAKE_CURRENT_BINARY_DIR}/icons.c - ${CMAKE_CURRENT_BINARY_DIR}/font.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h @@ -44,7 +43,6 @@ list(APPEND GUI_SRC set_source_files_properties( ${CMAKE_CURRENT_BINARY_DIR}/icons.c - ${CMAKE_CURRENT_BINARY_DIR}/font.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h @@ -65,10 +63,6 @@ add_custom_command(OUTPUT ${BINARY_NAME}.bnr COMMAND ${BANNERTOOL} makebanner -i ${CMAKE_CURRENT_SOURCE_DIR}/logo.png -a ${CMAKE_CURRENT_SOURCE_DIR}/bios.wav -o ${BINARY_NAME}.bnr DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/logo.png ${CMAKE_CURRENT_SOURCE_DIR}/bios.wav) -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.c - COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw - DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw) diff --git a/src/platform/3ds/ctr-gpu.c b/src/platform/3ds/ctr-gpu.c index bd17a606d..a17362fd2 100644 --- a/src/platform/3ds/ctr-gpu.c +++ b/src/platform/3ds/ctr-gpu.c @@ -27,11 +27,12 @@ struct ctrUIVertex { u32 abgr; }; -#define MAX_NUM_QUADS 1024 +#define MAX_NUM_QUADS 2048 #define VERTEX_BUFFER_SIZE MAX_NUM_QUADS * sizeof(struct ctrUIVertex) static struct ctrUIVertex* ctrVertexBuffer = NULL; -static u16 ctrNumQuads = 0; +static int ctrNumVerts = 0; +static int ctrVertStart = 0; static C3D_Tex* activeTexture = NULL; @@ -70,12 +71,6 @@ bool ctrInitGpu() { return false; } - // Set up TexEnv and other parameters - C3D_TexEnv* env = C3D_GetTexEnv(0); - C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0); - C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); - C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); - C3D_CullFace(GPU_CULL_NONE); C3D_DepthTest(false, GPU_ALWAYS, GPU_WRITE_ALL); C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); @@ -88,10 +83,6 @@ bool ctrInitGpu() { AttrInfo_AddLoader(attrInfo, 1, GPU_SHORT, 4); // in_tc0 AttrInfo_AddLoader(attrInfo, 2, GPU_UNSIGNED_BYTE, 4); // in_col - C3D_BufInfo* bufInfo = C3D_GetBufInfo(); - BufInfo_Init(bufInfo); - BufInfo_Add(bufInfo, ctrVertexBuffer, sizeof(struct ctrUIVertex), 3, 0x210); - return true; } @@ -129,9 +120,20 @@ void ctrActivateTexture(C3D_Tex* texture) { ctrFlushBatch(); } - C3D_TexBind(0, texture); activeTexture = texture; + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + if (texture->fmt < GPU_LA8) { + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0); + C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); + } else { + C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR, 0, 0); + C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0); + C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE); + C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE); + } + C3D_Mtx textureMtx = { .m = { // Rows are in the order w z y x, because ctrulib @@ -143,11 +145,14 @@ void ctrActivateTexture(C3D_Tex* texture) { } void ctrAddRectScaled(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh) { - if (ctrNumQuads == MAX_NUM_QUADS) { + if (ctrNumVerts + ctrVertStart == MAX_NUM_QUADS) { ctrFlushBatch(); + C3D_Flush(); + ctrNumVerts = 0; + ctrVertStart = 0; } - struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrNumQuads]; + struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrVertStart + ctrNumVerts]; vtx->x = x; vtx->y = y; vtx->w = w; @@ -158,7 +163,7 @@ void ctrAddRectScaled(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 u vtx->vh = vh; vtx->abgr = color; - ++ctrNumQuads; + ++ctrNumVerts; } void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h) { @@ -166,13 +171,19 @@ void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h) { } void ctrFlushBatch(void) { - if (ctrNumQuads == 0) { + if (ctrNumVerts == 0) { return; } - GSPGPU_FlushDataCache(ctrVertexBuffer, VERTEX_BUFFER_SIZE); - C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumQuads); - C3D_Flush(); + C3D_TexBind(0, activeTexture); - ctrNumQuads = 0; + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, &ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex), 3, 0x210); + + GSPGPU_FlushDataCache(ctrVertexBuffer, VERTEX_BUFFER_SIZE); + C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumVerts); + + ctrVertStart += ctrNumVerts; + ctrNumVerts = 0; } diff --git a/src/platform/3ds/font.raw b/src/platform/3ds/font.raw deleted file mode 100644 index 05b1436df325f5a4cbc2703202ed694b5fa3d149..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 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 j`hCx`t-~S zg8PV!jI4d01ozYP@@eG8&bS#ZPRE_`zB_-InP)J{jNKvkFnD77G;(8S+>92d<1TP{ z($GAfIz?w3>W&z9E%Q8+?|bRkYTK{%3NCYx4y&DU-`i7f<{3OtT@n9}^MBUAR1w0g z9}}`atGPA1UwQwxIQ4#Y6~FiF&ve+M*((IydE45DW$$O!E0yZ=j{ThJuk8Q2s_vJ& zpu5{+5O+pj>BxuZZ_a<_?*4S5{n&@Q&g+bE-D90Ht~3dMUbmDufZz6|9bqMm67V2k;#O`cjm7uJXKLu z3};rsJMig|I~>p)sFl(`j0xtJD$?xI3ldW zQM~#?-J?j(dsWZnK8yM@`uE(Vv+kNTv)}fURWtV|*U5gL*VR0@2WK)WLbh|h_Sk;1 zm^hXE+~w@M`y>3G)!k}O^323a#C_O8)qIF{mt!QiD%2!;jQKT|=kGf({x)%HJ+>Lf z{p>q)=Q`ECzW;@st57%U<@_8M5o`Ch0$VqEoD@|xAALMG8i`<;8chlO`Wf&Pi| z{JnzY3EN`MOrNKlxo1!R{v2`lc^cVKf$sN-Pt2>krDM##MW1w6^~tv5%t$MooXb-& zR@0fEkBl}(g_Tjgr;04}%{Z`%{Jou+bmyH{H9KY9vv8-ZD(FSG)(!>j z%R1QCBX2ROezIqMGOG5On>vok__QMDzGr-*a~1WIQS+X&Q7`ItRhRF&0(la9*)jQe z3b=_~mgjy39TaC6y+eJ|2eYWUhfOSZF~9HS?>p?heGT7!ohlDK&H z%X2-C+fPQ`{QmO2sQ#@wir0PgTI2evHEPRNwmz(2!EnZ%J<2q%{!|hA=rn&@-Te2G zBKQ!Ut>^voOlM?sqFiL;jUg;>~a|&~#MU~i*X)N)~C@^~7zuCAB)9}q2 zHNYBqMc%kml(3u=Q>KgDIlZ}aGK7}<)jr!}zRoz!F(acbi(WxDU(|Jtk>A+A`>g2X znpHjZ@0X{j>edSmT_3%VyjmfU>q%#4WbM&}NmvCepLQtO7yZB_pJ{JYD)~EmYsP33 zxvlRQ{mjZ$)EB*-!z4cI+vh1l$o=W;y*A%D|JcK%nY!yq*lH^=JQj=e z)6j#A9NXVd0!x9Vz*1l-uoPGdECrSVOM#`pQeY{t6j%x@1(pI!fu+DwU@5Q^SPCo!mI6zG zrNB~PDXVd0!x9Vz*1l-uoPGdECrSVOM#`pQeY{t6j%x@1(pI!fu+DwU@5Q^ MSPCo!KC8h00EbAi2LJ#7 diff --git a/src/platform/3ds/gui-font.c b/src/platform/3ds/gui-font.c index 67164290c..f044ce35c 100644 --- a/src/platform/3ds/gui-font.c +++ b/src/platform/3ds/gui-font.c @@ -8,36 +8,43 @@ #include "util/png-io.h" #include "util/vfs.h" #include "icons.h" -#include "font.h" #include "ctr-gpu.h" #define CELL_HEIGHT 16 #define CELL_WIDTH 16 -#define GLYPH_HEIGHT 12 +#define FONT_SIZE 0.52f struct GUIFont { - C3D_Tex texture; + C3D_Tex* sheets; C3D_Tex icons; }; struct GUIFont* GUIFontCreate(void) { + fontEnsureMapped(); struct GUIFont* guiFont = malloc(sizeof(struct GUIFont)); if (!guiFont) { return 0; } + C3D_Tex* tex; - C3D_Tex* tex = &guiFont->texture; - C3D_TexInitVRAM(tex, 256, 128, GPU_RGBA5551); + TGLP_s* glyphInfo = fontGetGlyphInfo(); + guiFont->sheets = malloc(sizeof(*guiFont->sheets) * glyphInfo->nSheets); - GSPGPU_FlushDataCache(font, font_size); - GX_RequestDma((u32*) font, tex->data, font_size); - gspWaitForDMA(); + int i; + for (i = 0; i < glyphInfo->nSheets; ++i) { + tex = &guiFont->sheets[i]; + tex->data = fontGetGlyphSheetTex(i); + tex->fmt = glyphInfo->sheetFmt; + tex->size = glyphInfo->sheetSize; + tex->width = glyphInfo->sheetWidth; + tex->height = glyphInfo->sheetHeight; + tex->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE); + } tex = &guiFont->icons; C3D_TexInitVRAM(tex, 256, 64, GPU_RGBA5551); - GSPGPU_FlushDataCache(icons, icons_size); GX_RequestDma((u32*) icons, tex->data, icons_size); gspWaitForDMA(); @@ -46,22 +53,24 @@ struct GUIFont* GUIFontCreate(void) { } void GUIFontDestroy(struct GUIFont* font) { - C3D_TexDelete(&font->texture); + free(font->sheets); C3D_TexDelete(&font->icons); free(font); } unsigned GUIFontHeight(const struct GUIFont* font) { UNUSED(font); - return GLYPH_HEIGHT; + return fontGetInfo()->lineFeed * FONT_SIZE; } unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) { UNUSED(font); - if (glyph > 0x7F) { - glyph = 0; + int index = fontGlyphIndexFromCodePoint(glyph); + charWidthInfo_s* info = fontGetCharWidthInfo(index); + if (info) { + return info->charWidth * FONT_SIZE; } - return defaultFontMetrics[glyph].width; + return 0; } void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) { @@ -84,19 +93,21 @@ void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* } void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint32_t color, uint32_t glyph) { - ctrActivateTexture(&font->texture); + int index = fontGlyphIndexFromCodePoint(glyph); + fontGlyphPos_s data; + fontCalcGlyphPos(&data, index, GLYPH_POS_CALC_VTXCOORD, 1.0, 1.0); - if (glyph > 0x7F) { - glyph = '?'; - } + C3D_Tex* tex = &font->sheets[data.sheetIndex]; + ctrActivateTexture(tex); - struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph]; - u16 x = glyph_x - metric.padding.left; - u16 y = glyph_y - GLYPH_HEIGHT; - u16 u = (glyph % 16u) * CELL_WIDTH; - u16 v = (glyph / 16u) * CELL_HEIGHT; + float width = data.texcoord.right - data.texcoord.left; + float height = data.texcoord.top - data.texcoord.bottom; + u16 x = glyph_x; + u16 y = glyph_y + tex->height * height / 8; + u16 u = tex->width * data.texcoord.left; + u16 v = tex->height * data.texcoord.bottom; - ctrAddRect(color, x, y, u, v, CELL_WIDTH, CELL_HEIGHT); + ctrAddRectScaled(color, x, y, tex->width * width * FONT_SIZE, tex->height * height * -FONT_SIZE, u, v, tex->width * width, tex->height * height); } void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) { diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index dea773398..6e9ca6488 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -178,6 +178,8 @@ static void _drawStart(void) { } static void _drawEnd(void) { + ctrFlushBatch(); + C3D_Flush(); C3D_RenderBufTransfer(&topScreen, (u32*) gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); C3D_RenderBufTransfer(&bottomScreen, (u32*) gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); gfxSwapBuffersGpu();