Skip to content

Commit 6bb2ea4

Browse files
authored
Add custom font example (#29)
1 parent 0c09528 commit 6bb2ea4

File tree

5 files changed

+367
-0
lines changed

5 files changed

+367
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ lib/
66
*.smdh
77
*.elf
88
*.t3x
9+
*.bcfnt
910
*~
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
#---------------------------------------------------------------------------------
2+
.SUFFIXES:
3+
#---------------------------------------------------------------------------------
4+
5+
ifeq ($(strip $(DEVKITARM)),)
6+
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
7+
endif
8+
9+
TOPDIR ?= $(CURDIR)
10+
include $(DEVKITARM)/3ds_rules
11+
12+
#---------------------------------------------------------------------------------
13+
# TARGET is the name of the output
14+
# BUILD is the directory where object files & intermediate files will be placed
15+
# SOURCES is a list of directories containing source code
16+
# DATA is a list of directories containing data files
17+
# INCLUDES is a list of directories containing header files
18+
# GRAPHICS is a list of directories containing graphics files
19+
# GFXBUILD is the directory where converted graphics files will be placed
20+
# If set to $(BUILD), it will statically link in the converted
21+
# files as if they were data files.
22+
#
23+
# NO_SMDH: if set to anything, no SMDH file is generated.
24+
# ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional)
25+
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
26+
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
27+
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
28+
# ICON is the filename of the icon (.png), relative to the project folder.
29+
# If not set, it attempts to use one of the following (in this order):
30+
# - <Project name>.png
31+
# - icon.png
32+
# - <libctru folder>/default_icon.png
33+
#---------------------------------------------------------------------------------
34+
TARGET := $(notdir $(CURDIR))
35+
BUILD := build
36+
SOURCES := source
37+
DATA := data
38+
INCLUDES := include
39+
GRAPHICS := gfx
40+
ROMFS := romfs
41+
GFXBUILD := $(ROMFS)
42+
#GFXBUILD := $(ROMFS)/gfx
43+
44+
#---------------------------------------------------------------------------------
45+
# options for code generation
46+
#---------------------------------------------------------------------------------
47+
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
48+
49+
CFLAGS := -g -Wall -O2 -mword-relocations \
50+
-fomit-frame-pointer -ffunction-sections \
51+
$(ARCH)
52+
53+
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
54+
55+
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
56+
57+
ASFLAGS := -g $(ARCH)
58+
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
59+
60+
LIBS := -lcitro2d -lcitro3d -lctru -lm
61+
62+
#---------------------------------------------------------------------------------
63+
# list of directories containing libraries, this must be the top level containing
64+
# include and lib
65+
#---------------------------------------------------------------------------------
66+
LIBDIRS := $(CTRULIB)
67+
68+
69+
#---------------------------------------------------------------------------------
70+
# no real need to edit anything past this point unless you need to add additional
71+
# rules for different file extensions
72+
#---------------------------------------------------------------------------------
73+
ifneq ($(BUILD),$(notdir $(CURDIR)))
74+
#---------------------------------------------------------------------------------
75+
76+
export OUTPUT := $(CURDIR)/$(TARGET)
77+
export TOPDIR := $(CURDIR)
78+
79+
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
80+
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \
81+
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
82+
83+
export DEPSDIR := $(CURDIR)/$(BUILD)
84+
85+
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
86+
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
87+
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
88+
PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica)))
89+
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
90+
GFXFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.t3s)))
91+
FONTFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.ttf)))
92+
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
93+
94+
#---------------------------------------------------------------------------------
95+
# use CXX for linking C++ projects, CC for standard C
96+
#---------------------------------------------------------------------------------
97+
ifeq ($(strip $(CPPFILES)),)
98+
#---------------------------------------------------------------------------------
99+
export LD := $(CC)
100+
#---------------------------------------------------------------------------------
101+
else
102+
#---------------------------------------------------------------------------------
103+
export LD := $(CXX)
104+
#---------------------------------------------------------------------------------
105+
endif
106+
#---------------------------------------------------------------------------------
107+
108+
#---------------------------------------------------------------------------------
109+
ifeq ($(GFXBUILD),$(BUILD))
110+
#---------------------------------------------------------------------------------
111+
export T3XFILES := $(GFXFILES:.t3s=.t3x)
112+
#---------------------------------------------------------------------------------
113+
else
114+
#---------------------------------------------------------------------------------
115+
export ROMFS_T3XFILES := $(patsubst %.t3s, $(GFXBUILD)/%.t3x, $(GFXFILES))
116+
export ROMFS_FONTFILES := $(patsubst %.ttf, $(GFXBUILD)/%.bcfnt, $(FONTFILES))
117+
export T3XHFILES := $(patsubst %.t3s, $(BUILD)/%.h, $(GFXFILES))
118+
#---------------------------------------------------------------------------------
119+
endif
120+
#---------------------------------------------------------------------------------
121+
122+
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
123+
124+
export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \
125+
$(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \
126+
$(addsuffix .o,$(T3XFILES))
127+
128+
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
129+
130+
export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(SHLISTFILES:.shlist=_shbin.h) \
131+
$(addsuffix .h,$(subst .,_,$(BINFILES))) \
132+
$(GFXFILES:.t3s=.h)
133+
134+
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
135+
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
136+
-I$(CURDIR)/$(BUILD)
137+
138+
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
139+
140+
export _3DSXDEPS := $(if $(NO_SMDH),,$(OUTPUT).smdh)
141+
142+
ifeq ($(strip $(ICON)),)
143+
icons := $(wildcard *.png)
144+
ifneq (,$(findstring $(TARGET).png,$(icons)))
145+
export APP_ICON := $(TOPDIR)/$(TARGET).png
146+
else
147+
ifneq (,$(findstring icon.png,$(icons)))
148+
export APP_ICON := $(TOPDIR)/icon.png
149+
endif
150+
endif
151+
else
152+
export APP_ICON := $(TOPDIR)/$(ICON)
153+
endif
154+
155+
ifeq ($(strip $(NO_SMDH)),)
156+
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
157+
endif
158+
159+
ifneq ($(ROMFS),)
160+
export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS)
161+
endif
162+
163+
.PHONY: all clean
164+
165+
#---------------------------------------------------------------------------------
166+
all: $(BUILD) $(GFXBUILD) $(DEPSDIR) $(ROMFS_T3XFILES) $(ROMFS_FONTFILES) $(T3XHFILES)
167+
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
168+
169+
$(BUILD):
170+
@mkdir -p $@
171+
172+
ifneq ($(GFXBUILD),$(BUILD))
173+
$(GFXBUILD):
174+
@mkdir -p $@
175+
endif
176+
177+
ifneq ($(DEPSDIR),$(BUILD))
178+
$(DEPSDIR):
179+
@mkdir -p $@
180+
endif
181+
182+
#---------------------------------------------------------------------------------
183+
clean:
184+
@echo clean ...
185+
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(GFXBUILD)
186+
187+
#---------------------------------------------------------------------------------
188+
$(GFXBUILD)/%.t3x $(BUILD)/%.h : %.t3s
189+
#---------------------------------------------------------------------------------
190+
@echo $(notdir $<)
191+
@tex3ds -i $< -H $(BUILD)/$*.h -d $(DEPSDIR)/$*.d -o $(GFXBUILD)/$*.t3x
192+
193+
#---------------------------------------------------------------------------------
194+
$(GFXBUILD)/%.bcfnt : %.ttf
195+
#---------------------------------------------------------------------------------
196+
@echo $(notdir $<)
197+
@mkbcfnt -o $(GFXBUILD)/$*.bcfnt $<
198+
199+
#---------------------------------------------------------------------------------
200+
else
201+
202+
#---------------------------------------------------------------------------------
203+
# main targets
204+
#---------------------------------------------------------------------------------
205+
$(OUTPUT).3dsx : $(OUTPUT).elf $(_3DSXDEPS)
206+
207+
$(OFILES_SOURCES) : $(HFILES)
208+
209+
$(OUTPUT).elf : $(OFILES)
210+
211+
#---------------------------------------------------------------------------------
212+
# you need a rule like this for each extension you use as binary data
213+
#---------------------------------------------------------------------------------
214+
%.bin.o %_bin.h : %.bin
215+
#---------------------------------------------------------------------------------
216+
@echo $(notdir $<)
217+
@$(bin2o)
218+
219+
#---------------------------------------------------------------------------------
220+
.PRECIOUS : %.t3x
221+
#---------------------------------------------------------------------------------
222+
%.t3x.o %_t3x.h : %.t3x
223+
#---------------------------------------------------------------------------------
224+
@echo $(notdir $<)
225+
@$(bin2o)
226+
227+
#---------------------------------------------------------------------------------
228+
# rules for assembling GPU shaders
229+
#---------------------------------------------------------------------------------
230+
define shader-as
231+
$(eval CURBIN := $*.shbin)
232+
$(eval DEPSFILE := $(DEPSDIR)/$*.shbin.d)
233+
echo "$(CURBIN).o: $< $1" > $(DEPSFILE)
234+
echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h
235+
echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h
236+
echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h
237+
picasso -o $(CURBIN) $1
238+
bin2s $(CURBIN) | $(AS) -o $*.shbin.o
239+
endef
240+
241+
%.shbin.o %_shbin.h : %.v.pica %.g.pica
242+
@echo $(notdir $^)
243+
@$(call shader-as,$^)
244+
245+
%.shbin.o %_shbin.h : %.v.pica
246+
@echo $(notdir $<)
247+
@$(call shader-as,$<)
248+
249+
%.shbin.o %_shbin.h : %.shlist
250+
@echo $(notdir $<)
251+
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)$(file)))
252+
253+
#---------------------------------------------------------------------------------
254+
%.t3x %.h : %.t3s
255+
#---------------------------------------------------------------------------------
256+
@echo $(notdir $<)
257+
@tex3ds -i $< -H $*.h -d $*.d -o $*.t3x
258+
259+
#---------------------------------------------------------------------------------
260+
%.bcfnt : %.ttf
261+
#---------------------------------------------------------------------------------
262+
@echo $(notdir $<)
263+
@mkbcfnt -o $*.bcfnt $<
264+
265+
-include $(DEPSDIR)/*.d
266+
267+
#---------------------------------------------------------------------------------------
268+
endif
269+
#---------------------------------------------------------------------------------------
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Font license available at https://www.fontsquirrel.com/license/liberation-serif
362 KB
Binary file not shown.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include <string.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <3ds.h>
5+
#include <citro2d.h>
6+
7+
C2D_TextBuf g_staticBuf;
8+
C2D_Text g_staticText[3];
9+
C2D_Font font[3];
10+
11+
static void sceneInit(void)
12+
{
13+
g_staticBuf = C2D_TextBufNew(4096); // support up to 4096 glyphs in the buffer
14+
font[0] = C2D_FontLoadSystem(CFG_REGION_USA);
15+
font[1] = C2D_FontLoadSystem(CFG_REGION_KOR);
16+
font[2] = C2D_FontLoad("romfs:/liberationitalic.bcfnt");
17+
18+
// Parse the text strings
19+
// Loads system font
20+
C2D_TextFontParse(&g_staticText[0], font[0], g_staticBuf, "A boring system font.");
21+
// Uses loaded font
22+
C2D_TextFontParse(&g_staticText[1], font[1], g_staticBuf, "이 텍스트는 한국어입니다.");
23+
// Uses other loaded font
24+
C2D_TextFontParse(&g_staticText[2], font[2], g_staticBuf, "Wow, this is interesting.");
25+
26+
// Optimize the text strings
27+
C2D_TextOptimize(&g_staticText[0]);
28+
C2D_TextOptimize(&g_staticText[1]);
29+
C2D_TextOptimize(&g_staticText[2]);
30+
}
31+
32+
static void sceneRender(float size)
33+
{
34+
// Draw static text strings
35+
float text2PosX = 400.0f - 16.0f - g_staticText[2].width*0.75f; // right-justify
36+
C2D_DrawText(&g_staticText[0], 0, 8.0f, 8.0f, 0.5f, size, size);
37+
C2D_DrawText(&g_staticText[1], C2D_AtBaseline, 108.0f, 36.0f, 0.5f, size, size);
38+
C2D_DrawText(&g_staticText[2], C2D_AtBaseline, text2PosX, 210.0f, 0.5f, size, size);
39+
}
40+
41+
static void sceneExit(void)
42+
{
43+
// Delete the text buffers
44+
C2D_TextBufDelete(g_staticBuf);
45+
C2D_FontFree(font[0]);
46+
C2D_FontFree(font[1]);
47+
C2D_FontFree(font[2]);
48+
}
49+
50+
int main()
51+
{
52+
romfsInit();
53+
cfguInit(); // Allow C2D_FontLoadSystem to work
54+
// Initialize the libs
55+
gfxInitDefault();
56+
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
57+
C2D_Init(C2D_DEFAULT_MAX_OBJECTS);
58+
C2D_Prepare();
59+
60+
// Create screen
61+
C3D_RenderTarget* top = C2D_CreateScreenTarget(GFX_TOP, GFX_LEFT);
62+
63+
// Initialize the scene
64+
sceneInit();
65+
66+
float size = 0.5f;
67+
68+
// Main loop
69+
while (aptMainLoop())
70+
{
71+
hidScanInput();
72+
73+
// Respond to user input
74+
u32 kDown = hidKeysDown();
75+
if (kDown & KEY_START)
76+
break; // break in order to return to hbmenu
77+
78+
// Render the scene
79+
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
80+
C2D_TargetClear(top, C2D_Color32(0x68, 0xB0, 0xD8, 0xFF));
81+
C2D_SceneBegin(top);
82+
sceneRender(size);
83+
C3D_FrameEnd(0);
84+
}
85+
86+
// Deinitialize the scene
87+
sceneExit();
88+
89+
// Deinitialize the libs
90+
C2D_Fini();
91+
C3D_Fini();
92+
romfsExit();
93+
cfguExit();
94+
gfxExit();
95+
return 0;
96+
}

0 commit comments

Comments
 (0)