3DS: Use system font for menus

This commit is contained in:
Jeffrey Pfau 2016-07-28 00:32:00 -07:00
parent 7930c5a350
commit 376c3e715e
6 changed files with 70 additions and 51 deletions

View File

@ -24,6 +24,7 @@ Misc:
- GBA Audio: Force audio DMAs to not increment destination - GBA Audio: Force audio DMAs to not increment destination
- Qt: Thread startup improvements - Qt: Thread startup improvements
- 3DS: Port to using citro3D - 3DS: Port to using citro3D
- 3DS: Use system font for menus
0.4.1: (2016-07-11) 0.4.1: (2016-07-11)
Bugfixes: Bugfixes:

View File

@ -30,7 +30,6 @@ set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE)
list(APPEND GUI_SRC list(APPEND GUI_SRC
${CMAKE_CURRENT_BINARY_DIR}/icons.c ${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.c
${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h
${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h
@ -44,7 +43,6 @@ list(APPEND GUI_SRC
set_source_files_properties( set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/icons.c ${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.c
${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h
${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.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 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) 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 add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c
COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw
DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw) DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw)

View File

@ -27,11 +27,12 @@ struct ctrUIVertex {
u32 abgr; u32 abgr;
}; };
#define MAX_NUM_QUADS 1024 #define MAX_NUM_QUADS 2048
#define VERTEX_BUFFER_SIZE MAX_NUM_QUADS * sizeof(struct ctrUIVertex) #define VERTEX_BUFFER_SIZE MAX_NUM_QUADS * sizeof(struct ctrUIVertex)
static struct ctrUIVertex* ctrVertexBuffer = NULL; static struct ctrUIVertex* ctrVertexBuffer = NULL;
static u16 ctrNumQuads = 0; static int ctrNumVerts = 0;
static int ctrVertStart = 0;
static C3D_Tex* activeTexture = NULL; static C3D_Tex* activeTexture = NULL;
@ -70,12 +71,6 @@ bool ctrInitGpu() {
return false; 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_CullFace(GPU_CULL_NONE);
C3D_DepthTest(false, GPU_ALWAYS, GPU_WRITE_ALL); 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); 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, 1, GPU_SHORT, 4); // in_tc0
AttrInfo_AddLoader(attrInfo, 2, GPU_UNSIGNED_BYTE, 4); // in_col 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; return true;
} }
@ -129,9 +120,20 @@ void ctrActivateTexture(C3D_Tex* texture) {
ctrFlushBatch(); ctrFlushBatch();
} }
C3D_TexBind(0, texture);
activeTexture = 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 = { C3D_Mtx textureMtx = {
.m = { .m = {
// Rows are in the order w z y x, because ctrulib // 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) { 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(); ctrFlushBatch();
C3D_Flush();
ctrNumVerts = 0;
ctrVertStart = 0;
} }
struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrNumQuads]; struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrVertStart + ctrNumVerts];
vtx->x = x; vtx->x = x;
vtx->y = y; vtx->y = y;
vtx->w = w; 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->vh = vh;
vtx->abgr = color; vtx->abgr = color;
++ctrNumQuads; ++ctrNumVerts;
} }
void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h) { 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) { void ctrFlushBatch(void) {
if (ctrNumQuads == 0) { if (ctrNumVerts == 0) {
return; return;
} }
GSPGPU_FlushDataCache(ctrVertexBuffer, VERTEX_BUFFER_SIZE); C3D_TexBind(0, activeTexture);
C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumQuads);
C3D_Flush();
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;
} }

Binary file not shown.

View File

@ -8,36 +8,43 @@
#include "util/png-io.h" #include "util/png-io.h"
#include "util/vfs.h" #include "util/vfs.h"
#include "icons.h" #include "icons.h"
#include "font.h"
#include "ctr-gpu.h" #include "ctr-gpu.h"
#define CELL_HEIGHT 16 #define CELL_HEIGHT 16
#define CELL_WIDTH 16 #define CELL_WIDTH 16
#define GLYPH_HEIGHT 12 #define FONT_SIZE 0.52f
struct GUIFont { struct GUIFont {
C3D_Tex texture; C3D_Tex* sheets;
C3D_Tex icons; C3D_Tex icons;
}; };
struct GUIFont* GUIFontCreate(void) { struct GUIFont* GUIFontCreate(void) {
fontEnsureMapped();
struct GUIFont* guiFont = malloc(sizeof(struct GUIFont)); struct GUIFont* guiFont = malloc(sizeof(struct GUIFont));
if (!guiFont) { if (!guiFont) {
return 0; return 0;
} }
C3D_Tex* tex;
C3D_Tex* tex = &guiFont->texture; TGLP_s* glyphInfo = fontGetGlyphInfo();
C3D_TexInitVRAM(tex, 256, 128, GPU_RGBA5551); guiFont->sheets = malloc(sizeof(*guiFont->sheets) * glyphInfo->nSheets);
GSPGPU_FlushDataCache(font, font_size); int i;
GX_RequestDma((u32*) font, tex->data, font_size); for (i = 0; i < glyphInfo->nSheets; ++i) {
gspWaitForDMA(); 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; tex = &guiFont->icons;
C3D_TexInitVRAM(tex, 256, 64, GPU_RGBA5551); C3D_TexInitVRAM(tex, 256, 64, GPU_RGBA5551);
GSPGPU_FlushDataCache(icons, icons_size); GSPGPU_FlushDataCache(icons, icons_size);
GX_RequestDma((u32*) icons, tex->data, icons_size); GX_RequestDma((u32*) icons, tex->data, icons_size);
gspWaitForDMA(); gspWaitForDMA();
@ -46,22 +53,24 @@ struct GUIFont* GUIFontCreate(void) {
} }
void GUIFontDestroy(struct GUIFont* font) { void GUIFontDestroy(struct GUIFont* font) {
C3D_TexDelete(&font->texture); free(font->sheets);
C3D_TexDelete(&font->icons); C3D_TexDelete(&font->icons);
free(font); free(font);
} }
unsigned GUIFontHeight(const struct GUIFont* font) { unsigned GUIFontHeight(const struct GUIFont* font) {
UNUSED(font); UNUSED(font);
return GLYPH_HEIGHT; return fontGetInfo()->lineFeed * FONT_SIZE;
} }
unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) { unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
UNUSED(font); UNUSED(font);
if (glyph > 0x7F) { int index = fontGlyphIndexFromCodePoint(glyph);
glyph = 0; 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) { 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) { 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) { C3D_Tex* tex = &font->sheets[data.sheetIndex];
glyph = '?'; ctrActivateTexture(tex);
}
struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph]; float width = data.texcoord.right - data.texcoord.left;
u16 x = glyph_x - metric.padding.left; float height = data.texcoord.top - data.texcoord.bottom;
u16 y = glyph_y - GLYPH_HEIGHT; u16 x = glyph_x;
u16 u = (glyph % 16u) * CELL_WIDTH; u16 y = glyph_y + tex->height * height / 8;
u16 v = (glyph / 16u) * CELL_HEIGHT; 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) { void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {

View File

@ -178,6 +178,8 @@ static void _drawStart(void) {
} }
static void _drawEnd(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(&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)); 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(); gfxSwapBuffersGpu();