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 05b1436df..000000000 Binary files a/src/platform/3ds/font.raw and /dev/null differ 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();